Renamed a public api function just because I can
Less access violations (AGAIN!)
Dumping now implies indexing too
Much better logic for automatically indexing files when FFAudioSource is used in avisynth
Changed defaults for FFIndex
Now FFmpeg's internal codec lists are used for lookup from the non-lavf based parts

Originally committed to SVN as r2991.
This commit is contained in:
Fredrik Mellbin 2009-05-28 19:33:14 +00:00
parent dfdea0298b
commit 841150b2b7
8 changed files with 122 additions and 313 deletions

View file

@ -93,18 +93,17 @@ void AvisynthVideoSource::InitOutputFormat(IScriptEnvironment *Env) {
VI.height = VP->Height;
// Crop to obey avisynth's even width/height requirements
if (VP->VPixelFormat == FFMS_GetPixFmt("yuvj420p") || VP->VPixelFormat == FFMS_GetPixFmt("yuv420p")) {
if (VI.pixel_type == VideoInfo::CS_I420) {
VI.height -= VI.height & 1;
VI.width -= VI.width & 1;
}
if (VP->VPixelFormat == FFMS_GetPixFmt("yuyv422")) {
if (VI.pixel_type == VideoInfo::CS_YUY2) {
VI.width -= VI.width & 1;
}
}
PVideoFrame AvisynthVideoSource::OutputFrame(const TAVFrameLite *Frame, IScriptEnvironment *Env) {
// Yes, this function is overly complex and could probably be simplified
TAVFrameLite *SrcPicture = const_cast<TAVFrameLite *>(Frame);
PVideoFrame Dst = Env->NewVideoFrame(VI);
@ -114,7 +113,7 @@ PVideoFrame AvisynthVideoSource::OutputFrame(const TAVFrameLite *Frame, IScriptE
Env->BitBlt(Dst->GetWritePtr(PLANAR_V), Dst->GetPitch(PLANAR_V), SrcPicture->Data[2], SrcPicture->Linesize[2], Dst->GetRowSize(PLANAR_V), Dst->GetHeight(PLANAR_V));
} else if (VI.IsRGB()) {
Env->BitBlt(Dst->GetWritePtr() + Dst->GetPitch() * (Dst->GetHeight() - 1), -Dst->GetPitch(), SrcPicture->Data[0], SrcPicture->Linesize[0], Dst->GetRowSize(), Dst->GetHeight());
} else {
} else { // YUY2
Env->BitBlt(Dst->GetWritePtr(), Dst->GetPitch(), SrcPicture->Data[0], SrcPicture->Linesize[0], Dst->GetRowSize(), Dst->GetHeight());
}

View file

@ -42,7 +42,7 @@ static AVSValue __cdecl CreateFFIndex(AVSValue Args, void* UserData, IScriptEnvi
const char *Source = Args[0].AsString();
const char *CacheFile = Args[1].AsString("");
int IndexMask = Args[2].AsInt(0);
int IndexMask = Args[2].AsInt(-1);
int DumpMask = Args[3].AsInt(0);
const char *AudioFile = Args[4].AsString("");
bool OverWrite = Args[5].AsBool(false);
@ -65,16 +65,16 @@ static AVSValue __cdecl CreateFFIndex(AVSValue Args, void* UserData, IScriptEnvi
if (!(Index = FFMS_MakeIndex(Source, IndexMask, DumpMask, FFMS_DefaultAudioFilename, NULL, true, NULL, NULL, ErrorMsg, MsgSize)))
Env->ThrowError("FFIndex: %s", ErrorMsg);
if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) {
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
Env->ThrowError("FFIndex: %s", ErrorMsg);
}
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
if (!OverWrite)
return AVSValue(1);
else
return AVSValue(2);
} else {
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
return AVSValue(0);
}
}
@ -127,7 +127,7 @@ static AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScri
if (Cache)
if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) {
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
Env->ThrowError("FFVideoSource: %s", ErrorMsg);
}
}
@ -139,7 +139,7 @@ static AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScri
if (strcmp(Timecodes, "")) {
if (FFMS_WriteTimecodes(FFMS_GetTrackFromIndex(Index, Track), Timecodes, ErrorMsg, MsgSize)) {
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
Env->ThrowError("FFVideoSource: %s", ErrorMsg);
}
}
@ -149,11 +149,11 @@ static AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScri
try {
Filter = new AvisynthVideoSource(Source, Track, Index, FPSNum, FPSDen, PP, Threads, SeekMode, Env, ErrorMsg, MsgSize);
} catch (...) {
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
throw;
}
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
return Filter;
}
@ -182,13 +182,34 @@ static AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScri
FFIndex *Index = NULL;
if (Cache)
Index = FFMS_ReadIndex(CacheFile, ErrorMsg, MsgSize);
// Index needs to be remade if it is an unindexed audio track
if (Index && Track >= 0 && Track < FFMS_GetNumTracks(Index)
&& FFMS_GetTrackType(FFMS_GetTrackFromIndex(Index, Track)) == FFMS_TYPE_AUDIO
&& FFMS_GetNumFrames(FFMS_GetTrackFromIndex(Index, Track)) == 0) {
FFMS_DestroyIndex(Index);
Index = NULL;
}
// More complicated for finding a default track, reindex the file if at least one audio track exists
if (Index && FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, ErrorMsg, MsgSize) >= 0
&& FFMS_GetFirstIndexedTrackOfType(Index, FFMS_TYPE_AUDIO, ErrorMsg, MsgSize) < 0) {
for (int i = 0; i < FFMS_GetNumTracks(Index); i++) {
if (FFMS_GetTrackType(FFMS_GetTrackFromIndex(Index, i)) == FFMS_TYPE_AUDIO) {
FFMS_DestroyIndex(Index);
Index = NULL;
break;
}
}
}
if (!Index) {
if (!(Index = FFMS_MakeIndex(Source, -1, 0, NULL, NULL, true, NULL, NULL, ErrorMsg, MsgSize)))
Env->ThrowError("FFAudioSource: %s", ErrorMsg);
if (Cache)
if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) {
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
Env->ThrowError("FFAudioSource: %s", ErrorMsg);
}
}
@ -203,11 +224,11 @@ static AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScri
try {
Filter = new AvisynthAudioSource(Source, Track, Index, Env, ErrorMsg, MsgSize);
} catch (...) {
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
throw;
}
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
return Filter;
}

View file

@ -50,6 +50,16 @@ FFMS_API(void) FFMS_SetLogLevel(int Level) {
}
FFMS_API(FFVideo *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FFIndex *Index, const char *PP, int Threads, int SeekMode, char *ErrorMsg, unsigned MsgSize) {
if (Track < 0 || Track >= Index->size()) {
_snprintf(ErrorMsg, MsgSize, "Out of bounds track index selected");
return NULL;
}
if (Index->at(Track).TT != FFMS_TYPE_VIDEO) {
_snprintf(ErrorMsg, MsgSize, "Not a video track");
return NULL;
}
try {
switch (Index->Decoder) {
case 0: return new FFLAVFVideo(SourceFile, Track, Index, PP, Threads, SeekMode, ErrorMsg, MsgSize);
@ -68,6 +78,16 @@ FFMS_API(FFVideo *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FF
}
FFMS_API(FFAudio *) FFMS_CreateAudioSource(const char *SourceFile, int Track, FFIndex *Index, char *ErrorMsg, unsigned MsgSize) {
if (Track < 0 || Track >= Index->size()) {
_snprintf(ErrorMsg, MsgSize, "Out of bounds track index selected");
return NULL;
}
if (Index->at(Track).TT != FFMS_TYPE_AUDIO) {
_snprintf(ErrorMsg, MsgSize, "Not an audio track");
return NULL;
}
try {
switch (Index->Decoder) {
case 0: return new FFLAVFAudio(SourceFile, Track, Index, ErrorMsg, MsgSize);
@ -121,7 +141,7 @@ FFMS_API(void) FFMS_ResetOutputFormat(FFVideo *V) {
V->ResetOutputFormat();
}
FFMS_API(void) FFMS_DestroyFFIndex(FFIndex *Index) {
FFMS_API(void) FFMS_DestroyIndex(FFIndex *Index) {
delete Index;
}
@ -197,11 +217,11 @@ FFMS_API(FFIndex *) FFMS_MakeIndex(const char *SourceFile, int IndexMask, int Du
}
FFMS_API(int) FFMS_DefaultAudioFilename(const char *SourceFile, int Track, const TAudioProperties *AP, char *FileName, void *Private) {
const char * FormatString = "%s.%d2.w64";
const char * FormatString = "%s.Track%d.delay%dms.w64";
if (FileName == NULL)
return _snprintf(NULL, 0, FormatString, SourceFile, Track) + 1;
return _snprintf(NULL, 0, FormatString, SourceFile, Track, (int)AP->FirstTime) + 1;
else
return _snprintf(FileName, 999999, FormatString, SourceFile, Track) + 1;
return _snprintf(FileName, 999999, FormatString, SourceFile, Track, (int)AP->FirstTime) + 1;
}
FFMS_API(FFIndexer *) FFMS_CreateIndexer(const char *SourceFile, char *ErrorMsg, unsigned MsgSize) {
@ -213,7 +233,7 @@ FFMS_API(FFIndexer *) FFMS_CreateIndexer(const char *SourceFile, char *ErrorMsg,
}
FFMS_API(FFIndex *) FFMS_DoIndexing(FFIndexer *Indexer, int IndexMask, int DumpMask, TAudioNameCallback ANC, void *ANCPrivate, bool IgnoreDecodeErrors, TIndexCallback IC, void *ICPrivate, char *ErrorMsg, unsigned MsgSize) {
Indexer->SetIndexMask(IndexMask);
Indexer->SetIndexMask(IndexMask | DumpMask);
Indexer->SetDumpMask(DumpMask);
Indexer->SetIgnoreDecodeErrors(IgnoreDecodeErrors);
Indexer->SetProgressCallback(IC, ICPrivate);

View file

@ -136,7 +136,7 @@ FFMS_API(const TAVFrameLite *) FFMS_GetFrameByTime(FFVideo *V, double Time, char
FFMS_API(int) FFMS_GetAudio(FFAudio *A, void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_SetOutputFormat(FFVideo *V, int64_t TargetFormats, int Width, int Height, char *ErrorMsg, unsigned MsgSize);
FFMS_API(void) FFMS_ResetOutputFormat(FFVideo *V);
FFMS_API(void) FFMS_DestroyFFIndex(FFIndex *Index);
FFMS_API(void) FFMS_DestroyIndex(FFIndex *Index);
FFMS_API(int) FFMS_GetFirstTrackOfType(FFIndex *Index, int TrackType, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_GetFirstIndexedTrackOfType(FFIndex *Index, int TrackType, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_GetNumTracks(FFIndex *Index);

View file

@ -12,9 +12,26 @@ Opens files using ffmpeg and nothing else. May be frame accurate on good days. T
<h2>Known issues</h2>
<ul>
<li>FFAudioSource() will have to remake any index implicitly created by FFVideoSource() and therefore code like
<pre>
AudioDub(FFVideoSource(X), FFAudioSource(X))
</pre>
will require two indexing passes. Apart from the time consumed this is harmless. To work around it open the audio first
<pre>
A = FFAudioSource(X)
V = FFVideoSource(X)
AudioDub(V, A)
</pre>
or use FFIndex().
<pre>
FFIndex(X)
AudioDub(FFVideoSource(X), FFAudioSource(X))
</pre>
</li>
<li>FFIndex() will silently ignore fatal decoding errors when indexing. This means that indexing a specific track may have failed even if FFIndex() succeeds.</li>
<li>Requires <a href='http://haali.cs.msu.ru/mkv/'>Haali's Media Splitter</a> if ogm or mpeg ps/ts is to be opened.</li>
<li>Avi files with NVOPs (sometimes occurs in xvid and such) will desync when these frames are encountered. Remux to mkv/mp4 before opening to solve it for now.</li>
<li>The audio sources still aren't sample accurate and sometimes exhibit many interesting issues. This is however more likely to be an issues when not using a 32bit windows compile. Dumping the audio during indexing is the only workaround.
<li>There are still some issues with FFAudioSource but it should be good enough for actual use in many cases now.</li>
</ul>
<h2>Compatibility - Video</h2>
@ -36,7 +53,7 @@ Opens files using ffmpeg and nothing else. May be frame accurate on good days. T
<h2>Usage</h2>
<p>
<b>FFIndex(string source, string cachefile = source + ".ffindex", int indexmask = 0, int dumpmask = 0, string audiofile = source, bool overwrite = false)</b><br />
<b>FFIndex(string source, string cachefile = source + ".ffindex", int indexmask = -1, int dumpmask = 0, string audiofile = source, bool overwrite = false)</b><br />
Used to invoke indexing separately and to write audio tracks to disk as wave64 files
</p>
@ -239,12 +256,16 @@ Note that --enable-w32threads or --enable-pthreads is required for multithreaded
<h2>Changes</h2>
<ul>
<li>2.00 beta 9<ul>
<li>Dumping audio now actually implies indexing too in FFIndex, previously nothing would be done if the index mask wasn't set as well</li>
<li>FFAudioSource will now first load the index and returns the first indexed audio track with track=-1, if no audio tracks are indexed or the chosen track isn't indexed the equivalent of FFIndex(indexmask = -1, overwrite = cache) is executed first</li>
<li>Codec lookup for non-lavf opened files now to a large part use the same lookup tables as lavf, this should improve the number of properly recognized codecs</li>
<li>Now uses the average framerate for files opened with Haali's splitters, before it was always reported as 30 fps</li>
<li>Implemented audio decoding using Haali's splitters, FFAudioSource now works on ts, ps and ogm</li>
<li>Can now be compiled with ICL 10.1 (probably other versions too)</li>
<li>How indexing works has been split internally so the track numbers and types are reported, this makes it possible to create an interactive GUI or ask which audio tracks are to be indexed</li>
<li>Now has stricter index checking to detect when different FFmpeg versions were used to create an index of the same version</li>
<li>Fixed memory leaks when audio sources were destroyed and when errors happened during indexing</li>
<li>Fixed access violations occurring when a track of the wrong type was specified or didn't exist in FFVideoSource and FFAudioSource</li>
<li>Fixed access violations occurring when unindexed or empty audio tracks in matroska/lavf read files were opened</li>
<li>Less type conversion/signedness warnings</li>
<li>When audio track dumping is performed a custom callback can now be supplied to name the tracks</li>

View file

@ -95,7 +95,7 @@ void TestFullDump1(char *SrcFile, bool WithAudio) {
assert(AVF);
}
FFMS_DestroyFFIndex(FI);
FFMS_DestroyIndex(FI);
FFMS_DestroyVideoSource(V);
}

View file

@ -217,19 +217,19 @@ int main(int argc, char *argv[]) {
DoIndexing();
} catch (const char *Error) {
std::cout << Error << std::endl;
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
return 1;
} catch (std::string Error) {
std::cout << std::endl << Error << std::endl;
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
return 1;
} catch (...) {
std::cout << std::endl << "Unknown error" << std::endl;
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
return 1;
}
FFMS_DestroyFFIndex(Index);
FFMS_DestroyIndex(Index);
#ifdef _WIN32
CoUninitialize();
#endif

View file

@ -28,6 +28,19 @@
# include <intrin.h>
#endif
// Export the array but not its data type... fun...
typedef struct CodecTags{
char str[20];
enum CodecID id;
} CodecTags;
extern "C" {
extern const AVCodecTag codec_bmp_tags[];
extern const CodecTags ff_mkv_codec_tags[];
extern const AVCodecTag codec_movvideo_tags[];
extern const AVCodecTag codec_wav_tags[];
}
#ifdef __UNIX__
#define _fseeki64 fseeko
#define _ftelli64 ftello
@ -399,292 +412,27 @@ typedef struct BITMAPINFOHEADER {
#endif
CodecID MatroskaToFFCodecID(char *Codec, void *CodecPrivate) {
/* Video Codecs */
if (!strcmp(Codec, "V_MS/VFW/FOURCC")) {
// fourcc list from ffdshow
switch (((BITMAPINFOHEADER *)CodecPrivate)->biCompression) {
case MAKEFOURCC('F', 'F', 'D', 'S'):
case MAKEFOURCC('F', 'V', 'F', 'W'):
case MAKEFOURCC('X', 'V', 'I', 'D'):
case MAKEFOURCC('D', 'I', 'V', 'X'):
case MAKEFOURCC('D', 'X', '5', '0'):
case MAKEFOURCC('M', 'P', '4', 'V'):
case MAKEFOURCC('m', 'p', '4', 'v'):
case MAKEFOURCC('3', 'I', 'V', 'X'):
case MAKEFOURCC('W', 'V', '1', 'F'):
case MAKEFOURCC('F', 'M', 'P', '4'):
case MAKEFOURCC('S', 'M', 'P', '4'):
return CODEC_ID_MPEG4;
case MAKEFOURCC('D', 'I', 'V', '3'):
case MAKEFOURCC('D', 'V', 'X', '3'):
case MAKEFOURCC('M', 'P', '4', '3'):
return CODEC_ID_MSMPEG4V3;
case MAKEFOURCC('M', 'P', '4', '2'):
return CODEC_ID_MSMPEG4V2;
case MAKEFOURCC('M', 'P', '4', '1'):
return CODEC_ID_MSMPEG4V1;
case MAKEFOURCC('W', 'M', 'V', '1'):
return CODEC_ID_WMV1;
case MAKEFOURCC('W', 'M', 'V', '2'):
return CODEC_ID_WMV2;
case MAKEFOURCC('W', 'M', 'V', '3'):
return CODEC_ID_WMV3;
/*
case MAKEFOURCC('M', 'S', 'S', '1'):
case MAKEFOURCC('M', 'S', 'S', '2'):
case MAKEFOURCC('W', 'V', 'P', '2'):
case MAKEFOURCC('W', 'M', 'V', 'P'):
return CODEC_ID_WMV9_LIB;
*/
case MAKEFOURCC('W', 'V', 'C', '1'):
return CODEC_ID_VC1;
case MAKEFOURCC('V', 'P', '5', '0'):
return CODEC_ID_VP5;
case MAKEFOURCC('V', 'P', '6', '0'):
case MAKEFOURCC('V', 'P', '6', '1'):
case MAKEFOURCC('V', 'P', '6', '2'):
return CODEC_ID_VP6;
case MAKEFOURCC('V', 'P', '6', 'F'):
case MAKEFOURCC('F', 'L', 'V', '4'):
return CODEC_ID_VP6F;
case MAKEFOURCC('C', 'A', 'V', 'S'):
return CODEC_ID_CAVS;
case MAKEFOURCC('M', 'P', 'G', '1'):
case MAKEFOURCC('M', 'P', 'E', 'G'):
return CODEC_ID_MPEG2VIDEO; // not a typo
case MAKEFOURCC('M', 'P', 'G', '2'):
case MAKEFOURCC('E', 'M', '2', 'V'):
case MAKEFOURCC('M', 'M', 'E', 'S'):
return CODEC_ID_MPEG2VIDEO;
case MAKEFOURCC('H', '2', '6', '3'):
case MAKEFOURCC('S', '2', '6', '3'):
case MAKEFOURCC('L', '2', '6', '3'):
case MAKEFOURCC('M', '2', '6', '3'):
case MAKEFOURCC('U', '2', '6', '3'):
case MAKEFOURCC('X', '2', '6', '3'):
return CODEC_ID_H263;
case MAKEFOURCC('H', '2', '6', '4'):
case MAKEFOURCC('X', '2', '6', '4'):
case MAKEFOURCC('V', 'S', 'S', 'H'):
case MAKEFOURCC('D', 'A', 'V', 'C'):
case MAKEFOURCC('P', 'A', 'V', 'C'):
case MAKEFOURCC('A', 'V', 'C', '1'):
return CODEC_ID_H264;
case MAKEFOURCC('M', 'J', 'P', 'G'):
case MAKEFOURCC('L', 'J', 'P', 'G'):
case MAKEFOURCC('M', 'J', 'L', 'S'):
case MAKEFOURCC('J', 'P', 'E', 'G'):
case MAKEFOURCC('A', 'V', 'R', 'N'):
case MAKEFOURCC('M', 'J', 'P', 'A'):
return CODEC_ID_MJPEG;
case MAKEFOURCC('D', 'V', 'S', 'D'):
case MAKEFOURCC('D', 'V', '2', '5'):
case MAKEFOURCC('D', 'V', '5', '0'):
case MAKEFOURCC('C', 'D', 'V', 'C'):
case MAKEFOURCC('C', 'D', 'V', '5'):
case MAKEFOURCC('D', 'V', 'I', 'S'):
case MAKEFOURCC('P', 'D', 'V', 'C'):
return CODEC_ID_DVVIDEO;
case MAKEFOURCC('H', 'F', 'Y', 'U'):
return CODEC_ID_HUFFYUV;
case MAKEFOURCC('F', 'F', 'V', 'H'):
return CODEC_ID_FFVHUFF;
case MAKEFOURCC('C', 'Y', 'U', 'V'):
return CODEC_ID_CYUV;
case MAKEFOURCC('A', 'S', 'V', '1'):
return CODEC_ID_ASV1;
case MAKEFOURCC('A', 'S', 'V', '2'):
return CODEC_ID_ASV2;
case MAKEFOURCC('V', 'C', 'R', '1'):
return CODEC_ID_VCR1;
case MAKEFOURCC('T', 'H', 'E', 'O'):
return CODEC_ID_THEORA;
case MAKEFOURCC('S', 'V', 'Q', '1'):
return CODEC_ID_SVQ1;
case MAKEFOURCC('S', 'V', 'Q', '3'):
return CODEC_ID_SVQ3;
case MAKEFOURCC('R', 'P', 'Z', 'A'):
return CODEC_ID_RPZA;
case MAKEFOURCC('F', 'F', 'V', '1'):
return CODEC_ID_FFV1;
case MAKEFOURCC('V', 'P', '3', '1'):
return CODEC_ID_VP3;
case MAKEFOURCC('R', 'L', 'E', '8'):
return CODEC_ID_MSRLE;
case MAKEFOURCC('M', 'S', 'Z', 'H'):
return CODEC_ID_MSZH;
case MAKEFOURCC('Z', 'L', 'I', 'B'):
return CODEC_ID_ZLIB;
case MAKEFOURCC('F', 'L', 'V', '1'):
return CODEC_ID_FLV1;
case MAKEFOURCC('P', 'N', 'G', '1'):
return CODEC_ID_PNG;
case MAKEFOURCC('M', 'P', 'N', 'G'):
return CODEC_ID_PNG;
/*
case MAKEFOURCC('A', 'V', 'I', 'S'):
return CODEC_ID_AVISYNTH;
*/
case MAKEFOURCC('C', 'R', 'A', 'M'):
return CODEC_ID_MSVIDEO1;
case MAKEFOURCC('R', 'T', '2', '1'):
return CODEC_ID_INDEO2;
case MAKEFOURCC('I', 'V', '3', '2'):
case MAKEFOURCC('I', 'V', '3', '1'):
return CODEC_ID_INDEO3;
case MAKEFOURCC('C', 'V', 'I', 'D'):
return CODEC_ID_CINEPAK;
case MAKEFOURCC('R', 'V', '1', '0'):
return CODEC_ID_RV10;
case MAKEFOURCC('R', 'V', '2', '0'):
return CODEC_ID_RV20;
case MAKEFOURCC('8', 'B', 'P', 'S'):
return CODEC_ID_8BPS;
case MAKEFOURCC('Q', 'R', 'L', 'E'):
return CODEC_ID_QTRLE;
case MAKEFOURCC('D', 'U', 'C', 'K'):
return CODEC_ID_TRUEMOTION1;
case MAKEFOURCC('T', 'M', '2', '0'):
return CODEC_ID_TRUEMOTION2;
case MAKEFOURCC('T', 'S', 'C', 'C'):
return CODEC_ID_TSCC;
case MAKEFOURCC('S', 'N', 'O', 'W'):
return CODEC_ID_SNOW;
case MAKEFOURCC('Q', 'P', 'E', 'G'):
case MAKEFOURCC('Q', '1', '_', '0'):
case MAKEFOURCC('Q', '1', '_', '1'):
return CODEC_ID_QPEG;
case MAKEFOURCC('H', '2', '6', '1'):
case MAKEFOURCC('M', '2', '6', '1'):
return CODEC_ID_H261;
case MAKEFOURCC('L', 'O', 'C', 'O'):
return CODEC_ID_LOCO;
case MAKEFOURCC('W', 'N', 'V', '1'):
return CODEC_ID_WNV1;
case MAKEFOURCC('C', 'S', 'C', 'D'):
return CODEC_ID_CSCD;
case MAKEFOURCC('Z', 'M', 'B', 'V'):
return CODEC_ID_ZMBV;
case MAKEFOURCC('U', 'L', 'T', 'I'):
return CODEC_ID_ULTI;
case MAKEFOURCC('V', 'I', 'X', 'L'):
return CODEC_ID_VIXL;
case MAKEFOURCC('A', 'A', 'S', 'C'):
return CODEC_ID_AASC;
case MAKEFOURCC('F', 'P', 'S', '1'):
return CODEC_ID_FRAPS;
default:
return CODEC_ID_NONE;
}
/* Look up native codecs */
for(int i = 0; ff_mkv_codec_tags[i].id != CODEC_ID_NONE; i++){
if(!strncmp(ff_mkv_codec_tags[i].str, Codec,
strlen(ff_mkv_codec_tags[i].str))){
return ff_mkv_codec_tags[i].id;
}
}
} else if (!strcmp(Codec, "V_MPEG4/ISO/AVC"))
return CODEC_ID_H264;
else if (!strcmp(Codec, "V_MPEG4/ISO/AP"))
return CODEC_ID_MPEG4;
else if (!strcmp(Codec, "V_MPEG4/ISO/ASP"))
return CODEC_ID_MPEG4;
else if (!strcmp(Codec, "V_MPEG4/ISO/SP"))
return CODEC_ID_MPEG4;
else if (!strcmp(Codec, "V_MPEG4/MS/V3"))
return CODEC_ID_MSMPEG4V3;
else if (!strcmp(Codec, "V_MPEG2"))
return CODEC_ID_MPEG2VIDEO;
else if (!strcmp(Codec, "V_MPEG1"))
return CODEC_ID_MPEG2VIDEO; // still not a typo
else if (!strcmp(Codec, "V_VC1"))
return CODEC_ID_VC1;
else if (!strcmp(Codec, "V_SNOW"))
return CODEC_ID_SNOW;
else if (!strcmp(Codec, "V_THEORA"))
return CODEC_ID_THEORA;
else if (!strcmp(Codec, "V_UNCOMPRESSED"))
return CODEC_ID_NONE; // FIXME: bleh
else if (!strcmp(Codec, "V_QUICKTIME"))
return CODEC_ID_SVQ3; // no idea if this is right
else if (!strcmp(Codec, "V_CIPC"))
return CODEC_ID_NONE; // don't know, don't care
else if (!strncmp(Codec, "V_REAL/RV", 9)) {
switch (Codec[9]) {
case '1':
return CODEC_ID_RV10;
case '2':
return CODEC_ID_RV20;
case '3':
return CODEC_ID_RV30;
case '4':
return CODEC_ID_RV40;
default:
return CODEC_ID_NONE;
}
/* Audio Codecs */
} else if (!strcmp(Codec, "A_AC3"))
return CODEC_ID_AC3;
else if (!strcmp(Codec, "A_EAC3"))
return CODEC_ID_AC3;
else if (!strcmp(Codec, "A_MPEG/L3"))
return CODEC_ID_MP3;
else if (!strcmp(Codec, "A_MPEG/L2"))
return CODEC_ID_MP2;
else if (!strcmp(Codec, "A_MPEG/L1"))
return CODEC_ID_MP2; // correct?
else if (!strcmp(Codec, "A_DTS"))
return CODEC_ID_DTS;
else if (!strcmp(Codec, "A_PCM/INT/LIT")) {
/* FIXME
switch (TI->AV.Audio.BitDepth) {
case 8: return CODEC_ID_PCM_S8;
case 16: return CODEC_ID_PCM_S16LE;
case 24: return CODEC_ID_PCM_S24LE;
case 32: return CODEC_ID_PCM_S32LE;
default: return CODEC_ID_NONE;
}
*/
return CODEC_ID_NONE;
} else if (!strcmp(Codec, "A_PCM/INT/BIG")) {
/* FIXME
switch (TI->AV.Audio.BitDepth) {
case 8: return CODEC_ID_PCM_S8;
case 16: return CODEC_ID_PCM_S16BE;
case 24: return CODEC_ID_PCM_S24BE;
case 32: return CODEC_ID_PCM_S32BE;
default: return CODEC_ID_NONE;
}
*/
return CODEC_ID_NONE;
} else if (!strcmp(Codec, "A_PCM/FLOAT/IEEE"))
return CODEC_ID_PCM_F32LE; // FIXME: only a most likely guess, may do bad things
else if (!strcmp(Codec, "A_FLAC"))
return CODEC_ID_FLAC;
else if (!strcmp(Codec, "A_MPC"))
return CODEC_ID_MUSEPACK8; // or is it CODEC_ID_MUSEPACK7? both?
else if (!strcmp(Codec, "A_TTA1"))
return CODEC_ID_TTA;
else if (!strcmp(Codec, "A_WAVPACK4"))
return CODEC_ID_WAVPACK;
else if (!strcmp(Codec, "A_VORBIS"))
return CODEC_ID_VORBIS;
else if (!strcmp(Codec, "A_REAL/14_4"))
return CODEC_ID_RA_144;
else if (!strcmp(Codec, "A_REAL/28_8"))
return CODEC_ID_RA_288;
else if (!strcmp(Codec, "A_REAL/COOK"))
return CODEC_ID_COOK;
else if (!strcmp(Codec, "A_REAL/SIPR"))
return CODEC_ID_SIPR;
else if (!strcmp(Codec, "A_REAL/ATRC"))
return CODEC_ID_ATRAC3;
else if (!strncmp(Codec, "A_AAC", 5))
return CODEC_ID_AAC;
else if (!strcmp(Codec, "A_SPEEX"))
return CODEC_ID_SPEEX;
else if (!strcmp(Codec, "A_QUICKTIME"))
return CODEC_ID_NONE; // no
else if (!strcmp(Codec, "A_MS/ACM")) {
// nothing useful here anyway?
/* Video codecs for "avi in mkv" mode */
const AVCodecTag *const tags[] = { codec_bmp_tags, 0 };
if (!strcmp(Codec, "V_MS/VFW/FOURCC"))
return av_codec_get_id(tags, ((BITMAPINFOHEADER *)CodecPrivate)->biCompression);
// FIXME
/* Audio codecs for "avi in mkv" mode */
//#include "Mmreg.h"
//((WAVEFORMATEX *)TI->CodecPrivate)->wFormatTag
return CODEC_ID_NONE;
} else {
return CODEC_ID_NONE;
}
/* Fixup for uncompressed video formats */
/* Fixup for uncompressed audio formats */
return CODEC_ID_NONE;
}