forked from mia/Aegisub
update ffms2 to r354
Originally committed to SVN as r4835.
This commit is contained in:
parent
6affce0581
commit
d6dde4ec73
18 changed files with 300 additions and 117 deletions
|
@ -22,7 +22,7 @@
|
|||
#define FFMS_H
|
||||
|
||||
// Version format: major - minor - micro - bump
|
||||
#define FFMS_VERSION ((2 << 24) | (13 << 16) | (1 << 8) | 0)
|
||||
#define FFMS_VERSION ((2 << 24) | (14 << 16) | (0 << 8) | 0)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -240,7 +240,7 @@ typedef int (FFMS_CC *TAudioNameCallback)(const char *SourceFile, int Track, con
|
|||
|
||||
// Most functions return 0 on success
|
||||
// Functions without error message output can be assumed to never fail in a graceful way
|
||||
FFMS_API(void) FFMS_Init(int CPUFeatures);
|
||||
FFMS_API(void) FFMS_Init(int CPUFeatures, int UseUTF8Paths);
|
||||
FFMS_API(int) FFMS_GetLogLevel();
|
||||
FFMS_API(void) FFMS_SetLogLevel(int Level);
|
||||
FFMS_API(FFMS_VideoSource *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FFMS_Index *Index, int Threads, int SeekMode, FFMS_ErrorInfo *ErrorInfo);
|
||||
|
|
|
@ -54,6 +54,12 @@
|
|||
# if (LIBAVCODEC_VERSION_INT) < (AV_VERSION_INT(52,30,2))
|
||||
# define AV_PKT_FLAG_KEY PKT_FLAG_KEY
|
||||
# endif
|
||||
# if (LIBAVCODEC_VERSION_INT) >= (AV_VERSION_INT(52,94,3)) // there are ~3 revisions where this will break but fixing that is :effort:
|
||||
# undef SampleFormat
|
||||
# else
|
||||
# define AVSampleFormat SampleFormat
|
||||
# define av_get_bits_per_sample_fmt av_get_bits_per_sample_format
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef LIBSWSCALE_VERSION_INT
|
||||
|
@ -64,5 +70,4 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif // FFMSCOMPAT_H
|
||||
|
|
|
@ -74,7 +74,7 @@ friend class FFSourceResources<FFMS_AudioSource>;
|
|||
protected:
|
||||
TAudioCache AudioCache;
|
||||
int64_t CurrentSample;
|
||||
std::vector<uint8_t> DecodingBuffer;
|
||||
AlignedBuffer<uint8_t> DecodingBuffer;
|
||||
FFMS_Track Frames;
|
||||
AVCodecContext *CodecContext;
|
||||
int AudioTrack;
|
||||
|
@ -106,7 +106,7 @@ class FFMatroskaAudio : public FFMS_AudioSource {
|
|||
private:
|
||||
MatroskaFile *MF;
|
||||
MatroskaReaderContext MC;
|
||||
CompressedStream *CS;
|
||||
TrackCompressionContext *TCC;
|
||||
char ErrorMessage[256];
|
||||
FFSourceResources<FFMS_AudioSource> Res;
|
||||
size_t PacketNumber;
|
||||
|
|
|
@ -33,6 +33,8 @@ static bool FFmpegInited = false;
|
|||
bool HasHaaliMPEG = false;
|
||||
bool HasHaaliOGG = false;
|
||||
int CPUFeatures = 0;
|
||||
bool GlobalUseUTF8Paths = false;
|
||||
|
||||
|
||||
#ifdef FFMS_WIN_DEBUG
|
||||
|
||||
|
@ -70,11 +72,19 @@ void av_log_windebug_callback(void* ptr, int level, const char* fmt, va_list vl)
|
|||
|
||||
#endif
|
||||
|
||||
FFMS_API(void) FFMS_Init(int CPUFeatures) {
|
||||
FFMS_API(void) FFMS_Init(int CPUFeatures, int UseUTF8Paths) {
|
||||
if (!FFmpegInited) {
|
||||
av_register_all();
|
||||
#if defined(_WIN32) && defined(FFMS_USE_UTF8_PATHS)
|
||||
ffms_patch_lavf_file_open();
|
||||
#ifdef _WIN32
|
||||
if (UseUTF8Paths) {
|
||||
ffms_patch_lavf_file_open();
|
||||
GlobalUseUTF8Paths = true;
|
||||
}
|
||||
else {
|
||||
GlobalUseUTF8Paths = false;
|
||||
}
|
||||
#else
|
||||
GlobalUseUTF8Paths = false;
|
||||
#endif
|
||||
#ifdef FFMS_WIN_DEBUG
|
||||
av_log_set_callback(av_log_windebug_callback);
|
||||
|
|
|
@ -33,6 +33,10 @@ extern "C" {
|
|||
extern bool HasHaaliMPEG;
|
||||
extern bool HasHaaliOGG;
|
||||
|
||||
#ifndef WITH_LIBPOSTPROC
|
||||
unsigned postproc_version(void) { return 0; } // ugly workaround to avoid lots of ifdeffing
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
|
||||
struct IndexHeader {
|
||||
uint32_t Id;
|
||||
uint32_t Version;
|
||||
|
@ -55,11 +59,12 @@ struct TrackHeader {
|
|||
uint32_t UseDTS;
|
||||
};
|
||||
|
||||
|
||||
SharedVideoContext::SharedVideoContext(bool FreeCodecContext) {
|
||||
CodecContext = NULL;
|
||||
Parser = NULL;
|
||||
CS = NULL;
|
||||
this->FreeCodecContext = FreeCodecContext;
|
||||
TCC = NULL;
|
||||
}
|
||||
|
||||
SharedVideoContext::~SharedVideoContext() {
|
||||
|
@ -72,15 +77,15 @@ SharedVideoContext::~SharedVideoContext() {
|
|||
if (Parser)
|
||||
av_parser_close(Parser);
|
||||
|
||||
if (CS)
|
||||
cs_Destroy(CS);
|
||||
if (TCC)
|
||||
delete TCC;
|
||||
}
|
||||
|
||||
SharedAudioContext::SharedAudioContext(bool FreeCodecContext) {
|
||||
W64Writer = NULL;
|
||||
CodecContext = NULL;
|
||||
CurrentSample = 0;
|
||||
CS = NULL;
|
||||
TCC = NULL;
|
||||
this->FreeCodecContext = FreeCodecContext;
|
||||
}
|
||||
|
||||
|
@ -92,8 +97,8 @@ SharedAudioContext::~SharedAudioContext() {
|
|||
av_freep(&CodecContext);
|
||||
}
|
||||
|
||||
if (CS)
|
||||
cs_Destroy(CS);
|
||||
if (TCC)
|
||||
delete TCC;
|
||||
}
|
||||
|
||||
TFrameInfo::TFrameInfo() {
|
||||
|
@ -322,6 +327,7 @@ void FFMS_Index::WriteIndex(const char *IndexFile) {
|
|||
IH.LAVCVersion = avcodec_version();
|
||||
IH.LSWSVersion = swscale_version();
|
||||
IH.LPPVersion = postproc_version();
|
||||
IH.LPPVersion = 0;
|
||||
IH.FileSize = Filesize;
|
||||
memcpy(IH.FileSignature, Digest, sizeof(Digest));
|
||||
|
||||
|
@ -512,7 +518,7 @@ FFMS_Indexer *FFMS_Indexer::CreateIndexer(const char *Filename) {
|
|||
}
|
||||
|
||||
// Do matroska indexing instead?
|
||||
if (!strcmp(FormatContext->iformat->name, "matroska")) {
|
||||
if (!strncmp(FormatContext->iformat->name, "matroska", 8)) {
|
||||
av_close_input_file(FormatContext);
|
||||
return new FFMatroskaIndexer(Filename);
|
||||
}
|
||||
|
@ -560,8 +566,8 @@ void FFMS_Indexer::WriteAudio(SharedAudioContext &AudioContext, FFMS_Index *Inde
|
|||
(*ANC)(SourceFile, Track, &AP, &WName[0], FNSize, ANCPrivate);
|
||||
std::string WN(&WName[0]);
|
||||
try {
|
||||
AudioContext.W64Writer = new Wave64Writer(WN.c_str(), av_get_bits_per_sample_format(AudioContext.CodecContext->sample_fmt),
|
||||
AudioContext.CodecContext->channels, AudioContext.CodecContext->sample_rate, (AudioContext.CodecContext->sample_fmt == SAMPLE_FMT_FLT) || (AudioContext.CodecContext->sample_fmt == SAMPLE_FMT_DBL));
|
||||
AudioContext.W64Writer = new Wave64Writer(WN.c_str(), av_get_bits_per_sample_fmt(AudioContext.CodecContext->sample_fmt),
|
||||
AudioContext.CodecContext->channels, AudioContext.CodecContext->sample_rate, (AudioContext.CodecContext->sample_fmt == AV_SAMPLE_FMT_FLT) || (AudioContext.CodecContext->sample_fmt == AV_SAMPLE_FMT_DBL));
|
||||
} catch (...) {
|
||||
throw FFMS_Exception(FFMS_ERROR_WAVE_WRITER, FFMS_ERROR_FILE_WRITE,
|
||||
"Failed to write wave data");
|
||||
|
|
|
@ -38,14 +38,13 @@
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
class SharedVideoContext {
|
||||
private:
|
||||
bool FreeCodecContext;
|
||||
public:
|
||||
AVCodecContext *CodecContext;
|
||||
AVCodecParserContext *Parser;
|
||||
CompressedStream *CS;
|
||||
TrackCompressionContext *TCC;
|
||||
|
||||
SharedVideoContext(bool FreeCodecContext);
|
||||
~SharedVideoContext();
|
||||
|
@ -58,7 +57,7 @@ public:
|
|||
AVCodecContext *CodecContext;
|
||||
Wave64Writer *W64Writer;
|
||||
int64_t CurrentSample;
|
||||
CompressedStream *CS;
|
||||
TrackCompressionContext *TCC;
|
||||
|
||||
SharedAudioContext(bool FreeCodecContext);
|
||||
~SharedAudioContext();
|
||||
|
@ -123,7 +122,7 @@ protected:
|
|||
TAudioNameCallback ANC;
|
||||
void *ANCPrivate;
|
||||
const char *SourceFile;
|
||||
std::vector<int16_t> DecodingBuffer;
|
||||
AlignedBuffer<int16_t> DecodingBuffer;
|
||||
|
||||
int64_t Filesize;
|
||||
uint8_t Digest[20];
|
||||
|
|
|
@ -69,7 +69,7 @@ FFLAVFAudio::FFLAVFAudio(const char *SourceFile, int Track, FFMS_Index *Index)
|
|||
}
|
||||
|
||||
void FFLAVFAudio::DecodeNextAudioBlock(int64_t *Count) {
|
||||
const size_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
const size_t SizeConst = (av_get_bits_per_sample_fmt(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
int Ret = -1;
|
||||
*Count = 0;
|
||||
uint8_t *Buf = &DecodingBuffer[0];
|
||||
|
@ -113,7 +113,7 @@ Done:;
|
|||
void FFLAVFAudio::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
||||
GetAudioCheck(Start, Count);
|
||||
|
||||
const int64_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
const int64_t SizeConst = (av_get_bits_per_sample_fmt(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
memset(Buf, 0, static_cast<size_t>(SizeConst * Count));
|
||||
|
||||
unsigned int PreDecBlocks = 0;
|
||||
|
|
|
@ -143,6 +143,10 @@ FFMS_Index *FFLAVFIndexer::DoIndexing() {
|
|||
"Invalid initial pts and dts");
|
||||
//
|
||||
|
||||
bool first = true;
|
||||
int LastNumChannels;
|
||||
int LastSampleRate;
|
||||
AVSampleFormat LastSampleFormat;
|
||||
while (TempPacket.size > 0) {
|
||||
int dbsize = AVCODEC_MAX_AUDIO_FRAME_SIZE*10;
|
||||
int Ret = avcodec_decode_audio3(AudioCodecContext, &DecodingBuffer[0], &dbsize, &TempPacket);
|
||||
|
@ -161,6 +165,25 @@ FFMS_Index *FFLAVFIndexer::DoIndexing() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
LastNumChannels = AudioCodecContext->channels;
|
||||
LastSampleRate = AudioCodecContext->sample_rate;
|
||||
LastSampleFormat = AudioCodecContext->sample_fmt;
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (LastNumChannels != AudioCodecContext->channels || LastSampleRate != AudioCodecContext->sample_rate
|
||||
|| LastSampleFormat != AudioCodecContext->sample_fmt) {
|
||||
std::ostringstream buf;
|
||||
buf <<
|
||||
"Audio format change detected. This is currently unsupported."
|
||||
<< " Channels: " << LastNumChannels << " -> " << AudioCodecContext->channels << ";"
|
||||
<< " Sample rate: " << LastSampleRate << " -> " << AudioCodecContext->sample_rate << ";"
|
||||
<< " Sample format: " << GetLAVCSampleFormatName(LastSampleFormat) << " -> "
|
||||
<< GetLAVCSampleFormatName(AudioCodecContext->sample_fmt);
|
||||
throw FFMS_Exception(FFMS_ERROR_UNSUPPORTED, FFMS_ERROR_DECODING, buf.str());
|
||||
}
|
||||
|
||||
if (Ret > 0) {
|
||||
TempPacket.size -= Ret;
|
||||
|
@ -168,7 +191,7 @@ FFMS_Index *FFLAVFIndexer::DoIndexing() {
|
|||
}
|
||||
|
||||
if (dbsize > 0)
|
||||
AudioContexts[Packet.stream_index].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_format(AudioCodecContext->sample_fmt) * AudioCodecContext->channels);
|
||||
AudioContexts[Packet.stream_index].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_fmt(AudioCodecContext->sample_fmt) * AudioCodecContext->channels);
|
||||
|
||||
if (DumpMask & (1 << Packet.stream_index))
|
||||
WriteAudio(AudioContexts[Packet.stream_index], TrackIndices.get(), Packet.stream_index, dbsize);
|
||||
|
@ -193,6 +216,7 @@ FFMS_TrackType FFLAVFIndexer::GetTrackType(int Track) {
|
|||
return static_cast<FFMS_TrackType>(FormatContext->streams[Track]->codec->codec_type);
|
||||
}
|
||||
|
||||
const char *FFLAVFIndexer::GetTrackCodec(int Track) {
|
||||
return (avcodec_find_decoder(FormatContext->streams[Track]->codec->codec_id))->name;
|
||||
const char *FFLAVFIndexer::GetTrackCodec(int Track) {
|
||||
AVCodec *codec = avcodec_find_decoder(FormatContext->streams[Track]->codec->codec_id);
|
||||
return codec ? codec->name : NULL;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "audiosource.h"
|
||||
|
||||
void FFMatroskaAudio::Free(bool CloseCodec) {
|
||||
if (CS)
|
||||
cs_Destroy(CS);
|
||||
if (TCC)
|
||||
delete TCC;
|
||||
if (MC.ST.fp) {
|
||||
mkv_Close(MF);
|
||||
fclose(MC.ST.fp);
|
||||
|
@ -37,7 +37,7 @@ FFMatroskaAudio::FFMatroskaAudio(const char *SourceFile, int Track, FFMS_Index *
|
|||
CodecContext = NULL;
|
||||
AVCodec *Codec = NULL;
|
||||
TrackInfo *TI = NULL;
|
||||
CS = NULL;
|
||||
TCC = NULL;
|
||||
PacketNumber = 0;
|
||||
Frames = (*Index)[Track];
|
||||
|
||||
|
@ -61,15 +61,8 @@ FFMatroskaAudio::FFMatroskaAudio(const char *SourceFile, int Track, FFMS_Index *
|
|||
|
||||
TI = mkv_GetTrackInfo(MF, Track);
|
||||
|
||||
if (TI->CompEnabled) {
|
||||
CS = cs_Create(MF, Track, ErrorMessage, sizeof(ErrorMessage));
|
||||
if (CS == NULL) {
|
||||
Free(false);
|
||||
std::ostringstream buf;
|
||||
buf << "Can't create decompressor: " << ErrorMessage;
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, buf.str());
|
||||
}
|
||||
}
|
||||
if (TI->CompEnabled)
|
||||
TCC = new TrackCompressionContext(MF, TI, Track);
|
||||
|
||||
CodecContext = avcodec_alloc_context();
|
||||
|
||||
|
@ -104,7 +97,7 @@ FFMatroskaAudio::FFMatroskaAudio(const char *SourceFile, int Track, FFMS_Index *
|
|||
void FFMatroskaAudio::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
||||
GetAudioCheck(Start, Count);
|
||||
|
||||
const int64_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
const int64_t SizeConst = (av_get_bits_per_sample_fmt(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
memset(Buf, 0, static_cast<size_t>(SizeConst * Count));
|
||||
|
||||
unsigned int PreDecBlocks = 0;
|
||||
|
@ -146,7 +139,7 @@ void FFMatroskaAudio::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
|||
}
|
||||
|
||||
void FFMatroskaAudio::DecodeNextAudioBlock(int64_t *Count) {
|
||||
const size_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
const size_t SizeConst = (av_get_bits_per_sample_fmt(CodecContext->sample_fmt) * CodecContext->channels) / 8;
|
||||
int Ret = -1;
|
||||
*Count = 0;
|
||||
uint8_t *Buf = &DecodingBuffer[0];
|
||||
|
@ -158,9 +151,9 @@ void FFMatroskaAudio::DecodeNextAudioBlock(int64_t *Count) {
|
|||
CurrentSample = FI.SampleStart + FI.SampleCount;
|
||||
PacketNumber++;
|
||||
|
||||
ReadFrame(FI.FilePos, FrameSize, CS, MC);
|
||||
ReadFrame(FI.FilePos, FrameSize, TCC, MC);
|
||||
TempPacket.data = MC.Buffer;
|
||||
TempPacket.size = FrameSize;
|
||||
TempPacket.size = (TCC && TCC->CompressionMethod == COMP_PREPEND) ? FrameSize + TCC->CompressedPrivateDataSize : FrameSize;
|
||||
if (FI.KeyFrame)
|
||||
TempPacket.flags = AV_PKT_FLAG_KEY;
|
||||
else
|
||||
|
|
|
@ -60,7 +60,7 @@ FFMatroskaIndexer::~FFMatroskaIndexer() {
|
|||
}
|
||||
|
||||
FFMS_Index *FFMatroskaIndexer::DoIndexing() {
|
||||
char ErrorMessage[256];
|
||||
// char ErrorMessage[256];
|
||||
std::vector<SharedAudioContext> AudioContexts(mkv_GetNumTracks(MF), SharedAudioContext(true));
|
||||
std::vector<SharedVideoContext> VideoContexts(mkv_GetNumTracks(MF), SharedVideoContext(true));
|
||||
|
||||
|
@ -83,14 +83,8 @@ FFMS_Index *FFMatroskaIndexer::DoIndexing() {
|
|||
"Could not open video codec");
|
||||
}
|
||||
|
||||
if (TI->CompEnabled) {
|
||||
VideoContexts[i].CS = cs_Create(MF, i, ErrorMessage, sizeof(ErrorMessage));
|
||||
if (VideoContexts[i].CS == NULL) {
|
||||
std::ostringstream buf;
|
||||
buf << "Can't create decompressor: " << ErrorMessage;
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, buf.str());
|
||||
}
|
||||
}
|
||||
if (TI->CompEnabled)
|
||||
VideoContexts[i].TCC = new TrackCompressionContext(MF, TI, i);
|
||||
|
||||
VideoContexts[i].CodecContext = CodecContext;
|
||||
VideoContexts[i].Parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
|
||||
|
@ -102,13 +96,12 @@ FFMS_Index *FFMatroskaIndexer::DoIndexing() {
|
|||
AudioContexts[i].CodecContext = AudioCodecContext;
|
||||
|
||||
if (TI->CompEnabled) {
|
||||
AudioContexts[i].CS = cs_Create(MF, i, ErrorMessage, sizeof(ErrorMessage));
|
||||
if (AudioContexts[i].CS == NULL) {
|
||||
try {
|
||||
AudioContexts[i].TCC = new TrackCompressionContext(MF, TI, i);
|
||||
} catch (FFMS_Exception &) {
|
||||
av_freep(&AudioCodecContext);
|
||||
AudioContexts[i].CodecContext = NULL;
|
||||
std::ostringstream buf;
|
||||
buf << "Can't create decompressor: " << ErrorMessage;
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, buf.str());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,17 +152,22 @@ FFMS_Index *FFMatroskaIndexer::DoIndexing() {
|
|||
|
||||
(*TrackIndices)[Track].push_back(TFrameInfo::VideoFrameInfo(StartTime, RepeatPict, (FrameFlags & FRAME_KF) != 0, FilePos, FrameSize));
|
||||
} else if (mkv_GetTrackInfo(MF, Track)->Type == TT_AUDIO && (IndexMask & (1 << Track))) {
|
||||
TrackCompressionContext *TCC = AudioContexts[Track].TCC;
|
||||
int64_t StartSample = AudioContexts[Track].CurrentSample;
|
||||
unsigned int CompressedFrameSize = FrameSize;
|
||||
AVCodecContext *AudioCodecContext = AudioContexts[Track].CodecContext;
|
||||
ReadFrame(FilePos, FrameSize, AudioContexts[Track].CS, MC);
|
||||
ReadFrame(FilePos, FrameSize, TCC, MC);
|
||||
TempPacket.data = MC.Buffer;
|
||||
TempPacket.size = FrameSize;
|
||||
TempPacket.size = (TCC && TCC->CompressionMethod == COMP_PREPEND) ? FrameSize + TCC->CompressedPrivateDataSize : FrameSize;
|
||||
if ((FrameFlags & FRAME_KF) != 0)
|
||||
TempPacket.flags = AV_PKT_FLAG_KEY;
|
||||
else
|
||||
TempPacket.flags = 0;
|
||||
|
||||
bool first = true;
|
||||
int LastNumChannels;
|
||||
int LastSampleRate;
|
||||
AVSampleFormat LastSampleFormat;
|
||||
while (TempPacket.size > 0) {
|
||||
int dbsize = AVCODEC_MAX_AUDIO_FRAME_SIZE*10;
|
||||
int Ret = avcodec_decode_audio3(AudioCodecContext, &DecodingBuffer[0], &dbsize, &TempPacket);
|
||||
|
@ -188,6 +186,25 @@ FFMS_Index *FFMatroskaIndexer::DoIndexing() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
LastNumChannels = AudioCodecContext->channels;
|
||||
LastSampleRate = AudioCodecContext->sample_rate;
|
||||
LastSampleFormat = AudioCodecContext->sample_fmt;
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (LastNumChannels != AudioCodecContext->channels || LastSampleRate != AudioCodecContext->sample_rate
|
||||
|| LastSampleFormat != AudioCodecContext->sample_fmt) {
|
||||
std::ostringstream buf;
|
||||
buf <<
|
||||
"Audio format change detected. This is currently unsupported."
|
||||
<< " Channels: " << LastNumChannels << " -> " << AudioCodecContext->channels << ";"
|
||||
<< " Sample rate: " << LastSampleRate << " -> " << AudioCodecContext->sample_rate << ";"
|
||||
<< " Sample format: " << GetLAVCSampleFormatName(LastSampleFormat) << " -> "
|
||||
<< GetLAVCSampleFormatName(AudioCodecContext->sample_fmt);
|
||||
throw FFMS_Exception(FFMS_ERROR_UNSUPPORTED, FFMS_ERROR_DECODING, buf.str());
|
||||
}
|
||||
|
||||
if (Ret > 0) {
|
||||
TempPacket.size -= Ret;
|
||||
|
@ -195,7 +212,7 @@ FFMS_Index *FFMatroskaIndexer::DoIndexing() {
|
|||
}
|
||||
|
||||
if (dbsize > 0)
|
||||
AudioContexts[Track].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_format(AudioCodecContext->sample_fmt) * AudioCodecContext->channels);
|
||||
AudioContexts[Track].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_fmt(AudioCodecContext->sample_fmt) * AudioCodecContext->channels);
|
||||
|
||||
if (DumpMask & (1 << Track))
|
||||
WriteAudio(AudioContexts[Track], TrackIndices.get(), Track, dbsize);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
//#include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
|
||||
|
||||
void FFMatroskaVideo::Free(bool CloseCodec) {
|
||||
if (CS)
|
||||
cs_Destroy(CS);
|
||||
if (TCC)
|
||||
delete TCC;
|
||||
if (MC.ST.fp) {
|
||||
mkv_Close(MF);
|
||||
fclose(MC.ST.fp);
|
||||
|
@ -41,7 +41,7 @@ FFMatroskaVideo::FFMatroskaVideo(const char *SourceFile, int Track,
|
|||
AVCodec *Codec = NULL;
|
||||
CodecContext = NULL;
|
||||
TrackInfo *TI = NULL;
|
||||
CS = NULL;
|
||||
TCC = NULL;
|
||||
PacketNumber = 0;
|
||||
VideoTrack = Track;
|
||||
Frames = (*Index)[VideoTrack];
|
||||
|
@ -65,15 +65,8 @@ FFMatroskaVideo::FFMatroskaVideo(const char *SourceFile, int Track,
|
|||
|
||||
TI = mkv_GetTrackInfo(MF, VideoTrack);
|
||||
|
||||
if (TI->CompEnabled) {
|
||||
CS = cs_Create(MF, VideoTrack, ErrorMessage, sizeof(ErrorMessage));
|
||||
if (CS == NULL) {
|
||||
Free(false);
|
||||
std::ostringstream buf;
|
||||
buf << "Can't create decompressor: " << ErrorMessage;
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, buf.str());
|
||||
}
|
||||
}
|
||||
if (TI->CompEnabled)
|
||||
TCC = new TrackCompressionContext(MF, TI, VideoTrack);
|
||||
|
||||
CodecContext = avcodec_alloc_context();
|
||||
if (avcodec_thread_init(CodecContext, Threads))
|
||||
|
@ -169,10 +162,10 @@ void FFMatroskaVideo::DecodeNextFrame() {
|
|||
// in the other sources where less is done manually
|
||||
const TFrameInfo &FI = Frames[Frames[PacketNumber].OriginalPos];
|
||||
FrameSize = FI.FrameSize;
|
||||
ReadFrame(FI.FilePos, FrameSize, CS, MC);
|
||||
ReadFrame(FI.FilePos, FrameSize, TCC, MC);
|
||||
|
||||
Packet.data = MC.Buffer;
|
||||
Packet.size = FrameSize;
|
||||
Packet.size = (TCC && TCC->CompressionMethod == COMP_PREPEND) ? FrameSize + TCC->CompressedPrivateDataSize : FrameSize;
|
||||
if (FI.KeyFrame)
|
||||
Packet.flags = AV_PKT_FLAG_KEY;
|
||||
else
|
||||
|
|
|
@ -26,15 +26,12 @@
|
|||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#ifdef FFMS_USE_UTF8_PATHS
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
extern "C" {
|
||||
# include "libavutil/avstring.h"
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
// Export the array but not its data type... fun...
|
||||
|
@ -51,6 +48,7 @@ extern const AVCodecTag ff_codec_wav_tags[];
|
|||
}
|
||||
|
||||
extern int CPUFeatures;
|
||||
extern bool GlobalUseUTF8Paths;
|
||||
|
||||
|
||||
|
||||
|
@ -81,6 +79,34 @@ int FFMS_Exception::CopyOut(FFMS_ErrorInfo *ErrorInfo) const {
|
|||
return (_ErrorType << 16) | _SubType;
|
||||
}
|
||||
|
||||
TrackCompressionContext::TrackCompressionContext(MatroskaFile *MF, TrackInfo *TI, unsigned int Track) {
|
||||
CS = NULL;
|
||||
CompressedPrivateData = NULL;
|
||||
CompressedPrivateDataSize = 0;
|
||||
CompressionMethod = TI->CompMethod;
|
||||
|
||||
if (CompressionMethod == COMP_ZLIB) {
|
||||
char ErrorMessage[512];
|
||||
CS = cs_Create(MF, Track, ErrorMessage, sizeof(ErrorMessage));
|
||||
if (CS == NULL) {
|
||||
std::ostringstream buf;
|
||||
buf << "Can't create MKV track decompressor: " << ErrorMessage;
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, buf.str());
|
||||
}
|
||||
} else if (CompressionMethod == COMP_PREPEND) {
|
||||
CompressedPrivateData = TI->CompMethodPrivate;
|
||||
CompressedPrivateDataSize = TI->CompMethodPrivateSize;
|
||||
} else {
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ,
|
||||
"Can't create MKV track decompressor: unknown or unsupported compression method");
|
||||
}
|
||||
}
|
||||
|
||||
TrackCompressionContext::~TrackCompressionContext() {
|
||||
if (CS)
|
||||
cs_Destroy(CS);
|
||||
}
|
||||
|
||||
int GetSWSCPUFlags() {
|
||||
int Flags = 0;
|
||||
|
||||
|
@ -101,6 +127,8 @@ int GetSWSCPUFlags() {
|
|||
int GetPPCPUFlags() {
|
||||
int Flags = 0;
|
||||
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
// not exactly a pretty solution but it'll never get called anyway
|
||||
if (CPUFeatures & FFMS_CPU_CAPS_MMX)
|
||||
Flags |= PP_CPU_CAPS_MMX;
|
||||
if (CPUFeatures & FFMS_CPU_CAPS_MMX2)
|
||||
|
@ -109,6 +137,7 @@ int GetPPCPUFlags() {
|
|||
Flags |= PP_CPU_CAPS_3DNOW;
|
||||
if (CPUFeatures & FFMS_CPU_CAPS_ALTIVEC)
|
||||
Flags |= PP_CPU_CAPS_ALTIVEC;
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
|
||||
return Flags;
|
||||
}
|
||||
|
@ -132,8 +161,20 @@ FFMS_TrackType HaaliTrackTypeToFFTrackType(int TT) {
|
|||
}
|
||||
}
|
||||
|
||||
void ReadFrame(uint64_t FilePos, unsigned int &FrameSize, CompressedStream *CS, MatroskaReaderContext &Context) {
|
||||
if (CS) {
|
||||
const char *GetLAVCSampleFormatName(AVSampleFormat s) {
|
||||
switch (s) {
|
||||
case AV_SAMPLE_FMT_U8: return "8-bit unsigned integer";
|
||||
case AV_SAMPLE_FMT_S16: return "16-bit signed integer";
|
||||
case AV_SAMPLE_FMT_S32: return "32-bit signed integer";
|
||||
case AV_SAMPLE_FMT_FLT: return "Single-precision floating point";
|
||||
case AV_SAMPLE_FMT_DBL: return "Double-precision floating point";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void ReadFrame(uint64_t FilePos, unsigned int &FrameSize, TrackCompressionContext *TCC, MatroskaReaderContext &Context) {
|
||||
if (TCC && TCC->CS) {
|
||||
CompressedStream *CS = TCC->CS;
|
||||
unsigned int DecompressedFrameSize = 0;
|
||||
|
||||
cs_NextFrame(CS, FilePos, FrameSize);
|
||||
|
@ -171,7 +212,23 @@ void ReadFrame(uint64_t FilePos, unsigned int &FrameSize, CompressedStream *CS,
|
|||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_SEEKING, buf.str());
|
||||
}
|
||||
|
||||
if (Context.BufferSize < FrameSize) {
|
||||
if (TCC && TCC->CompressionMethod == COMP_PREPEND) {
|
||||
unsigned ReqBufsize = FrameSize + TCC->CompressedPrivateDataSize + 16;
|
||||
if (Context.BufferSize < ReqBufsize) {
|
||||
Context.BufferSize = FrameSize + TCC->CompressedPrivateDataSize;
|
||||
Context.Buffer = (uint8_t *)realloc(Context.Buffer, ReqBufsize);
|
||||
if (Context.Buffer == NULL)
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_ALLOCATION_FAILED, "Out of memory");
|
||||
}
|
||||
|
||||
/* // maybe faster? maybe not?
|
||||
for (int i=0; i < TCC->CompressedPrivateDataSize; i++)
|
||||
*(Context.Buffer)++ = ((uint8_t *)TCC->CompressedPrivateData)[i];
|
||||
*/
|
||||
// screw it, memcpy and fuck the losers who use header compression
|
||||
memcpy(Context.Buffer, TCC->CompressedPrivateData, TCC->CompressedPrivateDataSize);
|
||||
}
|
||||
else if (Context.BufferSize < FrameSize) {
|
||||
Context.BufferSize = FrameSize;
|
||||
Context.Buffer = (uint8_t *)realloc(Context.Buffer, Context.BufferSize + 16);
|
||||
if (Context.Buffer == NULL)
|
||||
|
@ -179,8 +236,13 @@ void ReadFrame(uint64_t FilePos, unsigned int &FrameSize, CompressedStream *CS,
|
|||
"Out of memory");
|
||||
}
|
||||
|
||||
size_t ReadBytes = fread(Context.Buffer, 1, FrameSize, Context.ST.fp);
|
||||
uint8_t *TargetPtr = Context.Buffer;
|
||||
if (TCC && TCC->CompressionMethod == COMP_PREPEND)
|
||||
TargetPtr += TCC->CompressedPrivateDataSize;
|
||||
|
||||
size_t ReadBytes = fread(TargetPtr, 1, FrameSize, Context.ST.fp);
|
||||
if (ReadBytes != FrameSize) {
|
||||
return;
|
||||
if (ReadBytes == 0) {
|
||||
if (feof(Context.ST.fp)) {
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ,
|
||||
|
@ -210,8 +272,8 @@ void InitNullPacket(AVPacket &pkt) {
|
|||
|
||||
void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames) {
|
||||
AP.SampleFormat = static_cast<FFMS_SampleFormat>(CTX->sample_fmt);
|
||||
AP.BitsPerSample = av_get_bits_per_sample_format(CTX->sample_fmt);
|
||||
if (CTX->sample_fmt == SAMPLE_FMT_S32 && CTX->bits_per_raw_sample)
|
||||
AP.BitsPerSample = av_get_bits_per_sample_fmt(CTX->sample_fmt);
|
||||
if (CTX->sample_fmt == AV_SAMPLE_FMT_S32 && CTX->bits_per_raw_sample)
|
||||
AP.BitsPerSample = CTX->bits_per_raw_sample;
|
||||
|
||||
AP.Channels = CTX->channels;;
|
||||
|
@ -384,10 +446,12 @@ static wchar_t *dup_char_to_wchar(const char *s, unsigned int cp) {
|
|||
|
||||
FILE *ffms_fopen(const char *filename, const char *mode) {
|
||||
#ifdef _WIN32
|
||||
int codepage = CP_ACP;
|
||||
#ifdef FFMS_USE_UTF8_PATHS
|
||||
codepage = CP_UTF8;
|
||||
#endif
|
||||
unsigned int codepage;
|
||||
if (GlobalUseUTF8Paths)
|
||||
codepage = CP_UTF8;
|
||||
else
|
||||
codepage = CP_ACP;
|
||||
|
||||
FILE *ret;
|
||||
wchar_t *filename_wide = dup_char_to_wchar(filename, codepage);
|
||||
wchar_t *mode_wide = dup_char_to_wchar(mode, codepage);
|
||||
|
@ -406,18 +470,9 @@ FILE *ffms_fopen(const char *filename, const char *mode) {
|
|||
}
|
||||
|
||||
size_t ffms_mbstowcs (wchar_t *wcstr, const char *mbstr, size_t max) {
|
||||
#if defined(_WIN32) && defined(FFMS_USE_UTF8_PATHS)
|
||||
// try utf8 first
|
||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbstr, -1, NULL, 0);
|
||||
if (len > 0) {
|
||||
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbstr, -1, wcstr, max);
|
||||
return static_cast<size_t>(len);
|
||||
}
|
||||
// failed, use local ANSI codepage
|
||||
else {
|
||||
len = MultiByteToWideChar(CP_ACP, NULL, mbstr, -1, wcstr, max);
|
||||
return static_cast<size_t>(len);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
// this is only called by HaaliOpenFile anyway, so I think this is safe
|
||||
return static_cast<size_t>(MultiByteToWideChar((GlobalUseUTF8Paths ? CP_UTF8 : CP_ACP), MB_ERR_INVALID_CHARS, mbstr, -1, wcstr, max));
|
||||
#else
|
||||
return mbstowcs(wcstr, mbstr, max);
|
||||
#endif
|
||||
|
@ -430,10 +485,8 @@ void ffms_fstream::open(const char *filename, std::ios_base::openmode mode) {
|
|||
// that takes a wchar_t* filename, which means you can't open unicode
|
||||
// filenames with it on Windows. gg.
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
unsigned int codepage = CP_ACP;
|
||||
#if defined(FFMS_USE_UTF8_PATHS)
|
||||
codepage = CP_UTF8;
|
||||
#endif /* defined(FFMS_USE_UTF8_PATHS) */
|
||||
unsigned int codepage = GlobalUseUTF8Paths ? CP_UTF8 : CP_ACP;
|
||||
|
||||
wchar_t *filename_wide = dup_char_to_wchar(filename, codepage);
|
||||
if (filename_wide)
|
||||
std::fstream::open(filename_wide, mode);
|
||||
|
@ -441,9 +494,9 @@ void ffms_fstream::open(const char *filename, std::ios_base::openmode mode) {
|
|||
std::fstream::open(filename, mode);
|
||||
|
||||
free(filename_wide);
|
||||
#else /* defined(_WIN32) && !defined(__MINGW32__) */
|
||||
#else // defined(_WIN32) && !defined(__MINGW32__)
|
||||
std::fstream::open(filename, mode);
|
||||
#endif /* defined(_WIN32) && !defined(__MINGW32__) */
|
||||
#endif // defined(_WIN32) && !defined(__MINGW32__)
|
||||
}
|
||||
|
||||
ffms_fstream::ffms_fstream(const char *filename, std::ios_base::openmode mode) {
|
||||
|
@ -451,12 +504,12 @@ ffms_fstream::ffms_fstream(const char *filename, std::ios_base::openmode mode) {
|
|||
}
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(FFMS_USE_UTF8_PATHS)
|
||||
#ifdef _WIN32
|
||||
int ffms_wchar_open(const char *fname, int oflags, int pmode) {
|
||||
wchar_t *wfname = dup_char_to_wchar(fname, CP_UTF8);
|
||||
if (wfname) {
|
||||
int ret = _wopen(wfname, oflags, pmode);
|
||||
av_free(wfname);
|
||||
free(wfname);
|
||||
return ret;
|
||||
}
|
||||
return -1;
|
||||
|
@ -500,7 +553,7 @@ void ffms_patch_lavf_file_open() {
|
|||
proto->url_open = &ffms_lavf_file_open;
|
||||
}
|
||||
}
|
||||
#endif /* defined(_WIN32) && defined(FFMS_USE_UTF8_PATHS) */
|
||||
#endif // _WIN32
|
||||
|
||||
// End of filename hackery.
|
||||
|
||||
|
|
|
@ -30,10 +30,13 @@
|
|||
|
||||
extern "C" {
|
||||
#include "stdiostream.h"
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
#include <libpostproc/postprocess.h>
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
}
|
||||
|
||||
// must be included after ffmpeg headers
|
||||
|
@ -135,12 +138,44 @@ public:
|
|||
ffms_fstream(const char *filename, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class AlignedBuffer {
|
||||
T *buf;
|
||||
|
||||
public:
|
||||
AlignedBuffer(size_t n = 1) {
|
||||
buf = (T*) av_malloc(sizeof(*buf) * n);
|
||||
if (!buf) throw std::bad_alloc();
|
||||
}
|
||||
|
||||
~AlignedBuffer() {
|
||||
av_free(buf);
|
||||
buf = 0;
|
||||
}
|
||||
|
||||
const T &operator[] (size_t i) const { return buf[i]; }
|
||||
T &operator[] (size_t i) { return buf[i]; }
|
||||
};
|
||||
|
||||
|
||||
class TrackCompressionContext {
|
||||
public:
|
||||
CompressedStream *CS;
|
||||
unsigned CompressionMethod;
|
||||
void *CompressedPrivateData;
|
||||
unsigned CompressedPrivateDataSize;
|
||||
|
||||
TrackCompressionContext(MatroskaFile *MF, TrackInfo *TI, unsigned int Track);
|
||||
~TrackCompressionContext();
|
||||
};
|
||||
|
||||
|
||||
int GetSWSCPUFlags();
|
||||
int GetPPCPUFlags();
|
||||
void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo);
|
||||
FFMS_TrackType HaaliTrackTypeToFFTrackType(int TT);
|
||||
void ReadFrame(uint64_t FilePos, unsigned int &FrameSize, CompressedStream *CS, MatroskaReaderContext &Context);
|
||||
bool AudioFMTIsFloat(SampleFormat FMT);
|
||||
void ReadFrame(uint64_t FilePos, unsigned int &FrameSize, TrackCompressionContext *TCC, MatroskaReaderContext &Context);
|
||||
bool AudioFMTIsFloat(AVSampleFormat FMT);
|
||||
void InitNullPacket(AVPacket &pkt);
|
||||
void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames);
|
||||
#ifdef HAALISOURCE
|
||||
|
@ -152,14 +187,15 @@ void InitializeCodecContextFromMatroskaTrackInfo(TrackInfo *TI, AVCodecContext *
|
|||
CodecID MatroskaToFFCodecID(char *Codec, void *CodecPrivate, unsigned int FourCC = 0, unsigned int BitsPerSample = 0);
|
||||
FILE *ffms_fopen(const char *filename, const char *mode);
|
||||
size_t ffms_mbstowcs (wchar_t *wcstr, const char *mbstr, size_t max);
|
||||
#if defined(_WIN32) && defined(FFMS_USE_UTF8_PATHS)
|
||||
#ifdef _WIN32
|
||||
void ffms_patch_lavf_file_open();
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
#ifdef HAALISOURCE
|
||||
CComPtr<IMMContainer> HaaliOpenFile(const char *SourceFile, enum FFMS_Sources SourceMode);
|
||||
#endif
|
||||
#endif // HAALISOURCE
|
||||
void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext);
|
||||
void CorrectNTSCRationalFramerate(int *Num, int *Den);
|
||||
void CorrectTimebase(FFMS_VideoProperties *VP, FFMS_TrackTimeBase *TTimebase);
|
||||
const char *GetLAVCSampleFormatName(AVSampleFormat s);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,8 @@ void FFMS_VideoSource::GetFrameCheck(int n) {
|
|||
}
|
||||
|
||||
void FFMS_VideoSource::SetPP(const char *PP) {
|
||||
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
if (PPMode)
|
||||
pp_free_mode(PPMode);
|
||||
PPMode = NULL;
|
||||
|
@ -43,9 +45,14 @@ void FFMS_VideoSource::SetPP(const char *PP) {
|
|||
|
||||
ReAdjustPP(CodecContext->pix_fmt, CodecContext->width, CodecContext->height);
|
||||
OutputFrame(DecodeFrame);
|
||||
#else
|
||||
throw FFMS_Exception(FFMS_ERROR_POSTPROCESSING, FFMS_ERROR_UNSUPPORTED,
|
||||
"FFMS2 was not compiled with postprocessing support");
|
||||
#endif /* WITH_LIBPOSTPROC */
|
||||
}
|
||||
|
||||
void FFMS_VideoSource::ResetPP() {
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
if (PPContext)
|
||||
pp_free_context(PPContext);
|
||||
PPContext = NULL;
|
||||
|
@ -54,10 +61,12 @@ void FFMS_VideoSource::ResetPP() {
|
|||
pp_free_mode(PPMode);
|
||||
PPMode = NULL;
|
||||
|
||||
#endif /* WITH_LIBPOSTPROC */
|
||||
OutputFrame(DecodeFrame);
|
||||
}
|
||||
|
||||
void FFMS_VideoSource::ReAdjustPP(PixelFormat VPixelFormat, int Width, int Height) {
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
if (PPContext)
|
||||
pp_free_context(PPContext);
|
||||
PPContext = NULL;
|
||||
|
@ -82,8 +91,13 @@ void FFMS_VideoSource::ReAdjustPP(PixelFormat VPixelFormat, int Width, int Heigh
|
|||
|
||||
avpicture_free(&PPFrame);
|
||||
avpicture_alloc(&PPFrame, VPixelFormat, Width, Height);
|
||||
#else
|
||||
return;
|
||||
#endif /* WITH_LIBPOSTPROC */
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void CopyAVPictureFields(AVPicture &Picture, FFMS_Frame &Dst) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Dst.Data[i] = Picture.data[i];
|
||||
|
@ -99,6 +113,7 @@ FFMS_Frame *FFMS_VideoSource::OutputFrame(AVFrame *Frame) {
|
|||
ReAdjustOutputFormat(TargetPixelFormats, TargetWidth, TargetHeight, TargetResizer);
|
||||
}
|
||||
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
if (PPMode) {
|
||||
pp_postprocess(const_cast<const uint8_t **>(Frame->data), Frame->linesize, PPFrame.data, PPFrame.linesize, CodecContext->width, CodecContext->height, Frame->qscale_table, Frame->qstride, PPMode, PPContext, Frame->pict_type | (Frame->qscale_type ? PP_PICT_TYPE_QP2 : 0));
|
||||
if (SWS) {
|
||||
|
@ -119,6 +134,18 @@ FFMS_Frame *FFMS_VideoSource::OutputFrame(AVFrame *Frame) {
|
|||
}
|
||||
}
|
||||
}
|
||||
#else // WITH_LIBPOSTPROC
|
||||
if (SWS) {
|
||||
sws_scale(SWS, const_cast<FFMS_SWS_CONST_PARAM uint8_t **>(Frame->data), Frame->linesize, 0, CodecContext->height, SWSFrame.data, SWSFrame.linesize);
|
||||
CopyAVPictureFields(SWSFrame, LocalFrame);
|
||||
} else {
|
||||
// Special case to avoid ugly casts
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LocalFrame.Data[i] = Frame->data[i];
|
||||
LocalFrame.Linesize[i] = Frame->linesize[i];
|
||||
}
|
||||
}
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
|
||||
LocalFrame.EncodedWidth = CodecContext->width;
|
||||
LocalFrame.EncodedHeight = CodecContext->height;
|
||||
|
@ -157,8 +184,10 @@ FFMS_VideoSource::FFMS_VideoSource(const char *SourceFile, FFMS_Index *Index, in
|
|||
"The index does not match the source file");
|
||||
|
||||
memset(&VP, 0, sizeof(VP));
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
PPContext = NULL;
|
||||
PPMode = NULL;
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
SWS = NULL;
|
||||
LastFrameNum = 0;
|
||||
CurrentFrame = 1;
|
||||
|
@ -176,21 +205,26 @@ FFMS_VideoSource::FFMS_VideoSource(const char *SourceFile, FFMS_Index *Index, in
|
|||
DecodeFrame = avcodec_alloc_frame();
|
||||
|
||||
// Dummy allocations so the unallocated case doesn't have to be handled later
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
avpicture_alloc(&PPFrame, PIX_FMT_GRAY8, 16, 16);
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
avpicture_alloc(&SWSFrame, PIX_FMT_GRAY8, 16, 16);
|
||||
}
|
||||
|
||||
FFMS_VideoSource::~FFMS_VideoSource() {
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
if (PPMode)
|
||||
pp_free_mode(PPMode);
|
||||
|
||||
if (PPContext)
|
||||
pp_free_context(PPContext);
|
||||
|
||||
avpicture_free(&PPFrame);
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
|
||||
if (SWS)
|
||||
sws_freeContext(SWS);
|
||||
|
||||
avpicture_free(&PPFrame);
|
||||
avpicture_free(&SWSFrame);
|
||||
av_freep(&DecodeFrame);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ extern "C" {
|
|||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
#include <libpostproc/postprocess.h>
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
}
|
||||
|
||||
// must be included after ffmpeg headers
|
||||
|
@ -52,8 +54,10 @@ extern "C" {
|
|||
class FFMS_VideoSource {
|
||||
friend class FFSourceResources<FFMS_VideoSource>;
|
||||
private:
|
||||
#ifdef WITH_LIBPOSTPROC
|
||||
pp_context_t *PPContext;
|
||||
pp_mode_t *PPMode;
|
||||
#endif // WITH_LIBPOSTPROC
|
||||
SwsContext *SWS;
|
||||
int LastFrameHeight;
|
||||
int LastFrameWidth;
|
||||
|
@ -113,7 +117,7 @@ class FFMatroskaVideo : public FFMS_VideoSource {
|
|||
private:
|
||||
MatroskaFile *MF;
|
||||
MatroskaReaderContext MC;
|
||||
CompressedStream *CS;
|
||||
TrackCompressionContext *TCC;
|
||||
char ErrorMessage[256];
|
||||
FFSourceResources<FFMS_VideoSource> Res;
|
||||
size_t PacketNumber;
|
||||
|
@ -131,7 +135,6 @@ public:
|
|||
class FFHaaliVideo : public FFMS_VideoSource {
|
||||
private:
|
||||
CComPtr<IMMContainer> pMMC;
|
||||
std::vector<uint8_t> CodecPrivate;
|
||||
AVBitStreamFilterContext *BitStreamFilter;
|
||||
FFSourceResources<FFMS_VideoSource> Res;
|
||||
|
||||
|
|
|
@ -66,7 +66,13 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename)
|
|||
else if (res != RPC_E_CHANGED_MODE)
|
||||
throw AudioOpenError("COM initialization failure");
|
||||
#endif
|
||||
// initialize ffmpegsource
|
||||
// FIXME: CPU detection?
|
||||
#if FFMS_VERSION >= ((2 << 24) | (14 << 16) | (0 << 8) | 0)
|
||||
FFMS_Init(0, 1);
|
||||
#else
|
||||
FFMS_Init(0);
|
||||
#endif
|
||||
|
||||
ErrInfo.Buffer = FFMSErrMsg;
|
||||
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||
|
|
|
@ -77,7 +77,11 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename)
|
|||
#endif
|
||||
// initialize ffmpegsource
|
||||
// FIXME: CPU detection?
|
||||
#if FFMS_VERSION >= ((2 << 24) | (14 << 16) | (0 << 8) | 0)
|
||||
FFMS_Init(0, 1);
|
||||
#else
|
||||
FFMS_Init(0);
|
||||
#endif
|
||||
|
||||
ErrInfo.Buffer = FFMSErrMsg;
|
||||
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||
|
|
Loading…
Reference in a new issue