From 4b87a7a9ad3315f616bf007de6ac44268ebc84ab Mon Sep 17 00:00:00 2001 From: Fredrik Mellbin Date: Fri, 7 Sep 2007 20:07:27 +0000 Subject: [PATCH] FFmpegSource 1.11 Originally committed to SVN as r1556. --- FFmpegSource/ffbase.cpp | 21 +- FFmpegSource/ffmatroskasource.cpp | 520 +++++++++++++----------------- FFmpegSource/ffmpegsource.cpp | 19 +- FFmpegSource/ffmpegsource.h | 63 +++- FFmpegSource/ffmpegsource.html | 9 +- FFmpegSource/ffpp.cpp | 2 +- FFmpegSource/ffshared.cpp | 57 +++- FFmpegSource/stdiostream.c | 22 +- FFmpegSource/stdiostream.h | 30 +- 9 files changed, 427 insertions(+), 316 deletions(-) diff --git a/FFmpegSource/ffbase.cpp b/FFmpegSource/ffbase.cpp index 4fe399baf..24445a2fc 100644 --- a/FFmpegSource/ffbase.cpp +++ b/FFmpegSource/ffbase.cpp @@ -107,7 +107,7 @@ bool FFBase::SaveTimecodesToFile(const char *ATimecodeFile, int64_t ScaleD, int6 return true; } - +#ifdef FLAC_CACHE static FLAC__StreamDecoderReadStatus FLACStreamDecoderReadCallback(const FLAC__StreamDecoder *ADecoder, FLAC__byte ABuffer[], size_t *ABytes, FFBase *AOwner) { if(*ABytes > 0) { *ABytes = fread(ABuffer, sizeof(FLAC__byte), *ABytes, AOwner->FCFile); @@ -182,6 +182,7 @@ static void FLACStreamDecoderMetadataCallback(const FLAC__StreamDecoder *ADecode static void FLACStreamDecoderErrorCallback(const FLAC__StreamDecoder *ADecoder, FLAC__StreamDecoderErrorStatus AStatus, FFBase *AOwner) { AOwner->FCError = true; } +#endif // FLAC_CACHE bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env) { char DefaultCacheFilename[1024]; @@ -205,7 +206,8 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in return false; } - // If FLAC? +#ifdef FLAC_CACHE + // is FLAC? FLACAudioCache = FLAC__stream_decoder_new(); if (FLAC__stream_decoder_init_stream(FLACAudioCache, &(FLAC__StreamDecoderReadCallback)FLACStreamDecoderReadCallback, @@ -225,6 +227,7 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in } FLAC__stream_decoder_delete(FLACAudioCache); FLACAudioCache = NULL; +#endif // FLAC_CACHE // Raw audio VI.num_audio_samples = VI.AudioSamplesFromBytes(CacheSize); @@ -234,6 +237,7 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in return true; } +#ifdef FLAC_CACHE static FLAC__StreamEncoderWriteStatus FLACStreamEncoderWriteCallback(const FLAC__StreamEncoder *ASncoder, const FLAC__byte ABuffer[], size_t ABytes, unsigned ABamples, unsigned ACurrentFrame, FFBase *AOwner) { fwrite(ABuffer, sizeof(FLAC__byte), ABytes, AOwner->FCFile); if(ferror(AOwner->FCFile)) @@ -289,6 +293,7 @@ void FFBase::CloseFLACCacheWriter(FLAC__StreamEncoder *AFSE) { fclose(FCFile); FCFile = NULL; } +#endif // FLAC_CACHE FILE *FFBase::NewRawCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env) { char DefaultCacheFilename[1024]; @@ -392,16 +397,18 @@ PVideoFrame FFBase::OutputFrame(AVFrame *AFrame, IScriptEnvironment *Env) { return Dst; } -void __stdcall FFBase::GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment* Env) { +void FFBase::GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment* Env) { if (AudioCacheType == acRaw) { _fseeki64(RawAudioCache, VI.BytesFromAudioSamples(Start), SEEK_SET); fread(Buf, 1, VI.BytesFromAudioSamples(Count), RawAudioCache); +#ifdef FLAC_CACHE } else if (AudioCacheType == acFLAC) { FCCount = Count; FCBuffer = Buf; FLAC__stream_decoder_seek_absolute(FLACAudioCache, Start); while (FCCount > 0) FLAC__stream_decoder_process_single(FLACAudioCache); +#endif // FLAC_CACHE } else { Env->ThrowError("FFmpegSource: Audio requested but none available"); } @@ -412,12 +419,14 @@ FFBase::FFBase() { AudioCacheType = acNone; FCError = false; RawAudioCache = NULL; - FLACAudioCache = NULL; PPContext = NULL; PPMode = NULL; SWS = NULL; DecodingBuffer = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE]; +#ifdef FLAC_CACHE + FLACAudioCache = NULL; FLACBuffer = new FLAC__int32[AVCODEC_MAX_AUDIO_FRAME_SIZE]; +#endif // FLAC_CACHE FCFile = NULL; ConvertToFormat = PIX_FMT_NONE; memset(&PPPicture, 0, sizeof(PPPicture)); @@ -426,13 +435,15 @@ FFBase::FFBase() { FFBase::~FFBase() { delete [] DecodingBuffer; - delete [] FLACBuffer; if (RawAudioCache) fclose(RawAudioCache); +#ifdef FLAC_CACHE + delete [] FLACBuffer; if (FLACAudioCache) { FLAC__stream_decoder_finish(FLACAudioCache); FLAC__stream_decoder_delete(FLACAudioCache); } +#endif // FLAC_CACHE if (FCFile) fclose(FCFile); if (SWS) diff --git a/FFmpegSource/ffmatroskasource.cpp b/FFmpegSource/ffmatroskasource.cpp index 0266b3136..83a9a6d36 100644 --- a/FFmpegSource/ffmatroskasource.cpp +++ b/FFmpegSource/ffmatroskasource.cpp @@ -19,165 +19,208 @@ // THE SOFTWARE. #include "ffmpegsource.h" -#include "stdiostream.c" -class FFMatroskaSource : public FFBase { -private: - StdIoStream ST; - unsigned int BufferSize; - CompressedStream *VideoCS; - CompressedStream *AudioCS; +int FFMatroskaSource::GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env) { + if (Index == -1) + for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++) + if (mkv_GetTrackInfo(MF, i)->Type == ATrackType) { + Index = i; + break; + } - AVCodecContext *VideoCodecContext; + if (Index == -1) + Env->ThrowError("FFmpegSource: No %s track found", (ATrackType & TT_VIDEO) ? "video" : "audio"); + if (Index <= -2) + return -2; - MatroskaFile *MF; - char ErrorMessage[256]; - uint8_t *Buffer; + if (Index >= (int)mkv_GetNumTracks(MF)) + Env->ThrowError("FFmpegSource: Invalid %s track number", (ATrackType & TT_VIDEO) ? "video" : "audio"); - int CurrentFrame; + TrackInfo *TI = mkv_GetTrackInfo(MF, Index); - int ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, CompressedStream *ACS, IScriptEnvironment *Env); - int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, IScriptEnvironment* Env); + if (TI->Type != ATrackType) + Env->ThrowError("FFmpegSource: Selected track is not %s", (ATrackType & TT_VIDEO) ? "video" : "audio"); - int GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env) { - if (Index == -1) - for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++) - if (mkv_GetTrackInfo(MF, i)->Type == ATrackType) { - Index = i; - break; - } + return Index; +} - if (Index == -1) - Env->ThrowError("FFmpegSource: No %s track found", (ATrackType & TT_VIDEO) ? "video" : "audio"); - if (Index <= -2) - return -2; +FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, int AACCompression, const char *APPString, int AQuality, IScriptEnvironment* Env) { + CurrentFrame = 0; + int VideoTrack; + int AudioTrack; + unsigned int TrackMask = ~0; + AVCodecContext *AudioCodecContext = NULL; + AVCodec *AudioCodec = NULL; + VideoCodecContext = NULL; + AVCodec *VideoCodec = NULL; + TrackInfo *VideoTI = NULL; + BufferSize = 0; + Buffer = NULL; + VideoCS = NULL; + AudioCS = NULL; - if (Index >= (int)mkv_GetNumTracks(MF)) - Env->ThrowError("FFmpegSource: Invalid %s track number", (ATrackType & TT_VIDEO) ? "video" : "audio"); + memset(&ST,0,sizeof(ST)); + ST.base.read = (int (__cdecl *)(InputStream *,ulonglong,void *,int))StdIoRead; + ST.base.scan = (longlong (__cdecl *)(InputStream *,ulonglong,unsigned int))StdIoScan; + ST.base.getcachesize = (unsigned int (__cdecl *)(InputStream *))StdIoGetCacheSize; + ST.base.geterror = (const char *(__cdecl *)(InputStream *))StdIoGetLastError; + ST.base.memalloc = (void *(__cdecl *)(InputStream *,size_t))StdIoMalloc; + ST.base.memrealloc = (void *(__cdecl *)(InputStream *,void *,size_t))StdIoRealloc; + ST.base.memfree = (void (__cdecl *)(InputStream *,void *)) StdIoFree; + ST.base.progress = (int (__cdecl *)(InputStream *,ulonglong,ulonglong))StdIoProgress; - TrackInfo *TI = mkv_GetTrackInfo(MF, Index); + ST.fp = fopen(ASource, "rb"); + if (ST.fp == NULL) + Env->ThrowError("FFmpegSource: Can't open '%s': %s", ASource, strerror(errno)); - if (TI->Type != ATrackType) - Env->ThrowError("FFmpegSource: Selected track is not %s", (ATrackType & TT_VIDEO) ? "video" : "audio"); + setvbuf(ST.fp, NULL, _IOFBF, CACHESIZE); - return Index; + MF = mkv_OpenEx(&ST.base, 0, 0, ErrorMessage, sizeof(ErrorMessage)); + if (MF == NULL) { + fclose(ST.fp); + Env->ThrowError("FFmpegSource: Can't parse Matroska file: %s", ErrorMessage); } -public: - FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, int AACCompression, const char *APPString, int AQuality, IScriptEnvironment* Env) { - CurrentFrame = 0; - int VideoTrack; - int AudioTrack; - unsigned int TrackMask = ~0; - AVCodecContext *AudioCodecContext = NULL; - AVCodec *AudioCodec = NULL; - VideoCodecContext = NULL; - AVCodec *VideoCodec = NULL; - TrackInfo *VideoTI = NULL; - BufferSize = 0; - Buffer = NULL; - VideoCS = NULL; - AudioCS = NULL; + VideoTrack = GetTrackIndex(AVideoTrack, TT_VIDEO, Env); + AudioTrack = GetTrackIndex(AAudioTrack, TT_AUDIO, Env); - memset(&ST,0,sizeof(ST)); - ST.base.read = (int (__cdecl *)(InputStream *,ulonglong,void *,int))StdIoRead; - ST.base.scan = (longlong (__cdecl *)(InputStream *,ulonglong,unsigned int))StdIoScan; - ST.base.getcachesize = (unsigned int (__cdecl *)(InputStream *))StdIoGetCacheSize; - ST.base.geterror = (const char *(__cdecl *)(InputStream *))StdIoGetLastError; - ST.base.memalloc = (void *(__cdecl *)(InputStream *,size_t))StdIoMalloc; - ST.base.memrealloc = (void *(__cdecl *)(InputStream *,void *,size_t))StdIoRealloc; - ST.base.memfree = (void (__cdecl *)(InputStream *,void *)) StdIoFree; - ST.base.progress = (int (__cdecl *)(InputStream *,ulonglong,ulonglong))StdIoProgress; + bool VCacheIsValid = true; + bool ACacheIsValid = true; - ST.fp = fopen(ASource, "rb"); - if (ST.fp == NULL) - Env->ThrowError("FFmpegSource: Can't open '%s': %s", ASource, strerror(errno)); + if (VideoTrack >= 0) { + VCacheIsValid = LoadFrameInfoFromFile(AVideoCache, ASource, VideoTrack); - setvbuf(ST.fp, NULL, _IOFBF, CACHESIZE); + VideoTI = mkv_GetTrackInfo(MF, VideoTrack); - MF = mkv_OpenEx(&ST.base, 0, 0, ErrorMessage, sizeof(ErrorMessage)); - if (MF == NULL) { - fclose(ST.fp); - Env->ThrowError("FFmpegSource: Can't parse Matroska file: %s", ErrorMessage); + if (VideoTI->CompEnabled) { + VideoCS = cs_Create(MF, VideoTrack, ErrorMessage, sizeof(ErrorMessage)); + if (VideoCS == NULL) + Env->ThrowError("FFmpegSource: Can't create decompressor: %s", ErrorMessage); } - VideoTrack = GetTrackIndex(AVideoTrack, TT_VIDEO, Env); - AudioTrack = GetTrackIndex(AAudioTrack, TT_AUDIO, Env); + VideoCodecContext = avcodec_alloc_context(); + VideoCodecContext->extradata = (uint8_t *)VideoTI->CodecPrivate; + VideoCodecContext->extradata_size = VideoTI->CodecPrivateSize; - bool VCacheIsValid = true; - bool ACacheIsValid = true; + VideoCodec = avcodec_find_decoder(MatroskaToFFCodecID(VideoTI)); + if (VideoCodec == NULL) + Env->ThrowError("FFmpegSource: Video codec not found"); - if (VideoTrack >= 0) { - VCacheIsValid = LoadFrameInfoFromFile(AVideoCache, ASource, VideoTrack); + if (avcodec_open(VideoCodecContext, VideoCodec) < 0) + Env->ThrowError("FFmpegSource: Could not open video codec"); - VideoTI = mkv_GetTrackInfo(MF, VideoTrack); - - if (VideoTI->CompEnabled) { - VideoCS = cs_Create(MF, VideoTrack, ErrorMessage, sizeof(ErrorMessage)); - if (VideoCS == NULL) - Env->ThrowError("FFmpegSource: Can't create decompressor: %s", ErrorMessage); - } - - VideoCodecContext = avcodec_alloc_context(); - VideoCodecContext->extradata = (uint8_t *)VideoTI->CodecPrivate; - VideoCodecContext->extradata_size = VideoTI->CodecPrivateSize; - - VideoCodec = avcodec_find_decoder(MatroskaToFFCodecID(VideoTI)); - if (VideoCodec == NULL) - Env->ThrowError("FFmpegSource: Video codec not found"); - - if (avcodec_open(VideoCodecContext, VideoCodec) < 0) - Env->ThrowError("FFmpegSource: Could not open video codec"); - - // Fix for mpeg2 and other formats where decoding a frame is necessary to get information about the stream - if (VideoCodecContext->pix_fmt == PIX_FMT_NONE) { - mkv_SetTrackMask(MF, ~(1 << VideoTrack)); - int64_t Dummy; - DecodeNextFrame(DecodeFrame, &Dummy, Env); - mkv_Seek(MF, 0, MKVF_SEEK_TO_PREV_KEYFRAME); - } - - VI.image_type = VideoInfo::IT_TFF; - VI.width = VideoTI->AV.Video.PixelWidth; - VI.height = VideoTI->AV.Video.PixelHeight; - VI.fps_denominator = 1; - VI.fps_numerator = 30; - - SetOutputFormat(VideoCodecContext->pix_fmt, Env); - InitPP(VI.width, VI.height, APPString, AQuality, VideoCodecContext->pix_fmt, Env); - - if (!VCacheIsValid) - TrackMask &= ~(1 << VideoTrack); + // Fix for mpeg2 and other formats where decoding a frame is necessary to get information about the stream + if (VideoCodecContext->pix_fmt == PIX_FMT_NONE) { + mkv_SetTrackMask(MF, ~(1 << VideoTrack)); + int64_t Dummy; + DecodeNextFrame(DecodeFrame, &Dummy, Env); + mkv_Seek(MF, 0, MKVF_SEEK_TO_PREV_KEYFRAME); } - if (AudioTrack >= 0) { - TrackInfo *AudioTI = mkv_GetTrackInfo(MF, AudioTrack); + VI.image_type = VideoInfo::IT_TFF; + VI.width = VideoTI->AV.Video.PixelWidth; + VI.height = VideoTI->AV.Video.PixelHeight; + VI.fps_denominator = 1; + VI.fps_numerator = 30; - if (AudioTI->CompEnabled) { - AudioCS = cs_Create(MF, AudioTrack, ErrorMessage, sizeof(ErrorMessage)); - if (AudioCS == NULL) - Env->ThrowError("FFmpegSource: Can't create decompressor: %s", ErrorMessage); + SetOutputFormat(VideoCodecContext->pix_fmt, Env); + InitPP(VI.width, VI.height, APPString, AQuality, VideoCodecContext->pix_fmt, Env); + + if (!VCacheIsValid) + TrackMask &= ~(1 << VideoTrack); + } + + if (AudioTrack >= 0) { + TrackInfo *AudioTI = mkv_GetTrackInfo(MF, AudioTrack); + + if (AudioTI->CompEnabled) { + AudioCS = cs_Create(MF, AudioTrack, ErrorMessage, sizeof(ErrorMessage)); + if (AudioCS == NULL) + Env->ThrowError("FFmpegSource: Can't create decompressor: %s", ErrorMessage); + } + + AudioCodecContext = avcodec_alloc_context(); + AudioCodecContext->extradata = (uint8_t *)AudioTI->CodecPrivate; + AudioCodecContext->extradata_size = AudioTI->CodecPrivateSize; + + AudioCodec = avcodec_find_decoder(MatroskaToFFCodecID(AudioTI)); + if (AudioCodec == NULL) + Env->ThrowError("FFmpegSource: Audio codec not found"); + + if (avcodec_open(AudioCodecContext, AudioCodec) < 0) + Env->ThrowError("FFmpegSource: Could not open audio codec"); + + // Fix for ac3 and other codecs where decoding a block of audio is required to get information about it + if (AudioCodecContext->channels == 0 || AudioCodecContext->sample_rate == 0) { + mkv_SetTrackMask(MF, ~(1 << AudioTrack)); + uint64_t StartTime, EndTime, FilePos; + unsigned int Track, FrameFlags, FrameSize; + mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags); + + uint8_t DecodingBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE]; + int Size = ReadFrame(FilePos, FrameSize, AudioCS, Env); + uint8_t *Data = Buffer; + + while (Size > 0) { + int TempOutputBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; + int Ret = avcodec_decode_audio2(AudioCodecContext, (int16_t *)DecodingBuffer, &TempOutputBufSize, Data, Size); + if (Ret < 0) + Env->ThrowError("FFmpegSource: Audio decoding error"); + + Size -= Ret; + Data += Ret; } - AudioCodecContext = avcodec_alloc_context(); - AudioCodecContext->extradata = (uint8_t *)AudioTI->CodecPrivate; - AudioCodecContext->extradata_size = AudioTI->CodecPrivateSize; + mkv_Seek(MF, 0, MKVF_SEEK_TO_PREV_KEYFRAME); + } - AudioCodec = avcodec_find_decoder(MatroskaToFFCodecID(AudioTI)); - if (AudioCodec == NULL) - Env->ThrowError("FFmpegSource: Audio codec not found"); + VI.nchannels = AudioCodecContext->channels; + VI.audio_samples_per_second = AudioCodecContext->sample_rate; - if (avcodec_open(AudioCodecContext, AudioCodec) < 0) - Env->ThrowError("FFmpegSource: Could not open audio codec"); + switch (AudioCodecContext->sample_fmt) { + case SAMPLE_FMT_U8: VI.sample_type = SAMPLE_INT8; AACCompression = -1; break; + case SAMPLE_FMT_S16: VI.sample_type = SAMPLE_INT16; break; + case SAMPLE_FMT_S24: VI.sample_type = SAMPLE_INT24; AACCompression = -1; break; + case SAMPLE_FMT_S32: VI.sample_type = SAMPLE_INT32; AACCompression = -1; break; + case SAMPLE_FMT_FLT: VI.sample_type = SAMPLE_FLOAT; AACCompression = -1; break; + default: + Env->ThrowError("FFmpegSource: Unsupported/unknown sample format"); + } - // Fix for ac3 and other codecs where decoding a block of audio is required to get information about it - if (AudioCodecContext->channels == 0 || AudioCodecContext->sample_rate == 0) { - mkv_SetTrackMask(MF, ~(1 << AudioTrack)); - uint64_t StartTime, EndTime, FilePos; - unsigned int Track, FrameFlags, FrameSize; - mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags); + ACacheIsValid = OpenAudioCache(AAudioCache, ASource, AudioTrack, Env); + if (!ACacheIsValid) + TrackMask &= ~(1 << AudioTrack); + } - uint8_t DecodingBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE]; + mkv_SetTrackMask(MF, TrackMask); + + // Needs to be indexed? + if (!ACacheIsValid || !VCacheIsValid) { +#ifdef FLAC_CACHE + FLAC__StreamEncoder *FSE = NULL; +#endif // FLAC_CACHE + FILE *RawCache = NULL; + if (!ACacheIsValid) + if (AACCompression >= 0) + AudioCacheType = acFLAC; + else + AudioCacheType = acRaw; + + switch (AudioCacheType) { +#ifdef FLAC_CACHE + case acFLAC: FSE = NewFLACCacheWriter(AAudioCache, ASource, AudioTrack, AACCompression, Env); break; +#endif // FLAC_CACHE + case acRaw: RawCache = NewRawCacheWriter(AAudioCache, ASource, AudioTrack, Env); break; + } + + uint64_t StartTime, EndTime, FilePos; + unsigned int Track, FrameFlags, FrameSize; + + while (mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0) + if (Track == VideoTrack && !VCacheIsValid) { + FrameToDTS.push_back(FrameInfo(StartTime, (FrameFlags & FRAME_KF) != 0)); + VI.num_frames++; + } else if (Track == AudioTrack && !ACacheIsValid) { int Size = ReadFrame(FilePos, FrameSize, AudioCS, Env); uint8_t *Data = Buffer; @@ -187,138 +230,79 @@ public: if (Ret < 0) Env->ThrowError("FFmpegSource: Audio decoding error"); + int DecodedSamples = VI.AudioSamplesFromBytes(TempOutputBufSize); + Size -= Ret; Data += Ret; - } + VI.num_audio_samples += DecodedSamples; - mkv_Seek(MF, 0, MKVF_SEEK_TO_PREV_KEYFRAME); + if (AudioCacheType == acRaw) { + fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache); +#ifdef FLAC_CACHE + } else if (AudioCacheType == acFLAC) { + for (int i = 0; i < DecodedSamples * VI.nchannels; i++) + FLACBuffer[i] = ((int16_t *)DecodingBuffer)[i]; + FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples); +#endif // FLAC_CACHE + } + } } - VI.nchannels = AudioCodecContext->channels; - VI.audio_samples_per_second = AudioCodecContext->sample_rate; - - switch (AudioCodecContext->sample_fmt) { - case SAMPLE_FMT_U8: VI.sample_type = SAMPLE_INT8; AACCompression = -1; break; - case SAMPLE_FMT_S16: VI.sample_type = SAMPLE_INT16; break; - case SAMPLE_FMT_S24: VI.sample_type = SAMPLE_INT24; AACCompression = -1; break; - case SAMPLE_FMT_S32: VI.sample_type = SAMPLE_INT32; AACCompression = -1; break; - case SAMPLE_FMT_FLT: VI.sample_type = SAMPLE_FLOAT; AACCompression = -1; break; - default: - Env->ThrowError("FFmpegSource: Unsupported/unknown sample format"); + if (!ACacheIsValid) { + switch (AudioCacheType) { +#ifdef FLAC_CACHE + case acFLAC: CloseFLACCacheWriter(FSE); break; +#endif // FLAC_CACHE + case acRaw: CloseRawCacheWriter(RawCache); break; } ACacheIsValid = OpenAudioCache(AAudioCache, ASource, AudioTrack, Env); if (!ACacheIsValid) - TrackMask &= ~(1 << AudioTrack); + Env->ThrowError("FFmpegSource: Failed to open newly created audio cache for reading"); } - mkv_SetTrackMask(MF, TrackMask); + if (VideoTrack >= 0 && VI.num_frames == 0) + Env->ThrowError("FFmpegSource: Video track contains no frames"); - // Needs to be indexed? - if (!ACacheIsValid || !VCacheIsValid) { + if (AudioTrack >= 0 && VI.num_audio_samples == 0) + Env->ThrowError("FFmpegSource: Audio track contains no samples"); - FLAC__StreamEncoder *FSE = NULL; - FILE *RawCache = NULL; - if (!ACacheIsValid) - if (AACCompression >= 0) - AudioCacheType = acFLAC; - else - AudioCacheType = acRaw; + if (VideoTrack >= 0) + mkv_Seek(MF, FrameToDTS.front().DTS, MKVF_SEEK_TO_PREV_KEYFRAME); - switch (AudioCacheType) { - case acFLAC: FSE = NewFLACCacheWriter(AAudioCache, ASource, AudioTrack, AACCompression, Env); break; - case acRaw: RawCache = NewRawCacheWriter(AAudioCache, ASource, AudioTrack, Env); break; - } - - uint64_t StartTime, EndTime, FilePos; - unsigned int Track, FrameFlags, FrameSize; - - while (mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0) - if (Track == VideoTrack && !VCacheIsValid) { - FrameToDTS.push_back(FrameInfo(StartTime, (FrameFlags & FRAME_KF) != 0)); - VI.num_frames++; - } else if (Track == AudioTrack && !ACacheIsValid) { - int Size = ReadFrame(FilePos, FrameSize, AudioCS, Env); - uint8_t *Data = Buffer; - - while (Size > 0) { - int TempOutputBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; - int Ret = avcodec_decode_audio2(AudioCodecContext, (int16_t *)DecodingBuffer, &TempOutputBufSize, Data, Size); - if (Ret < 0) - Env->ThrowError("FFmpegSource: Audio decoding error"); - - int DecodedSamples = VI.AudioSamplesFromBytes(TempOutputBufSize); - - Size -= Ret; - Data += Ret; - VI.num_audio_samples += DecodedSamples; - - if (AudioCacheType == acFLAC) { - for (int i = 0; i < DecodedSamples * VI.nchannels; i++) - FLACBuffer[i] = ((int16_t *)DecodingBuffer)[i]; - FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples); - } else if (AudioCacheType == acRaw) { - fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache); - } - } - } - - if (!ACacheIsValid) { - switch (AudioCacheType) { - case acFLAC: CloseFLACCacheWriter(FSE); break; - case acRaw: CloseRawCacheWriter(RawCache); break; - } - - ACacheIsValid = OpenAudioCache(AAudioCache, ASource, AudioTrack, Env); - if (!ACacheIsValid) - Env->ThrowError("FFmpegSource: Failed to open newly created audio cache for reading"); - } - - if (VideoTrack >= 0 && VI.num_frames == 0) - Env->ThrowError("FFmpegSource: Video track contains no frames"); - - if (AudioTrack >= 0 && VI.num_audio_samples == 0) - Env->ThrowError("FFmpegSource: Audio track contains no samples"); - - if (VideoTrack >= 0) - mkv_Seek(MF, FrameToDTS.front().DTS, MKVF_SEEK_TO_PREV_KEYFRAME); - - if (AVCache && !VCacheIsValid) - if (!SaveFrameInfoToFile(AVideoCache, ASource, VideoTrack)) - Env->ThrowError("FFmpegSource: Failed to write video cache info"); - } - - if (AudioTrack >= 0) { - avcodec_close(AudioCodecContext); - av_free(AudioCodecContext); - } - - if (VideoTrack >= 0) { - mkv_SetTrackMask(MF, ~(1 << VideoTrack)); - - // Calculate the average framerate - if (FrameToDTS.size() >= 2) { - double DTSDiff = (double)(FrameToDTS.back().DTS - FrameToDTS.front().DTS); - VI.fps_denominator = (unsigned int)(DTSDiff * mkv_TruncFloat(VideoTI->TimecodeScale) / (double)1000 / (double)(VI.num_frames - 1) + 0.5); - VI.fps_numerator = 1000000; - } - - if (!SaveTimecodesToFile(ATimecodes, mkv_TruncFloat(VideoTI->TimecodeScale), 1000000)) - Env->ThrowError("FFmpegSource: Failed to write timecodes"); - } + if (AVCache && !VCacheIsValid) + if (!SaveFrameInfoToFile(AVideoCache, ASource, VideoTrack)) + Env->ThrowError("FFmpegSource: Failed to write video cache info"); } - ~FFMatroskaSource() { - free(Buffer); - mkv_Close(MF); - fclose(ST.fp); - if (VideoCodecContext) - avcodec_close(VideoCodecContext); - av_free(VideoCodecContext); + if (AudioTrack >= 0) { + avcodec_close(AudioCodecContext); + av_free(AudioCodecContext); } - PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env); -}; + if (VideoTrack >= 0) { + mkv_SetTrackMask(MF, ~(1 << VideoTrack)); + + // Calculate the average framerate + if (FrameToDTS.size() >= 2) { + double DTSDiff = (double)(FrameToDTS.back().DTS - FrameToDTS.front().DTS); + VI.fps_denominator = (unsigned int)(DTSDiff * mkv_TruncFloat(VideoTI->TimecodeScale) / (double)1000 / (double)(VI.num_frames - 1) + 0.5); + VI.fps_numerator = 1000000; + } + + if (!SaveTimecodesToFile(ATimecodes, mkv_TruncFloat(VideoTI->TimecodeScale), 1000000)) + Env->ThrowError("FFmpegSource: Failed to write timecodes"); + } +} + +FFMatroskaSource::~FFMatroskaSource() { + free(Buffer); + mkv_Close(MF); + fclose(ST.fp); + if (VideoCodecContext) + avcodec_close(VideoCodecContext); + av_free(VideoCodecContext); +} int FFMatroskaSource::ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, CompressedStream *ACS, IScriptEnvironment *Env) { if (ACS) { @@ -401,7 +385,7 @@ Done: return Ret; } -PVideoFrame __stdcall FFMatroskaSource::GetFrame(int n, IScriptEnvironment* Env) { +PVideoFrame FFMatroskaSource::GetFrame(int n, IScriptEnvironment* Env) { bool HasSeeked = false; if (n < CurrentFrame || FindClosestKeyFrame(n) > CurrentFrame) { @@ -426,53 +410,3 @@ PVideoFrame __stdcall FFMatroskaSource::GetFrame(int n, IScriptEnvironment* Env) return OutputFrame(DecodeFrame, Env); } - -AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) { - if (!UserData) { - av_register_all(); - UserData = (void *)-1; - } - - if (!Args[0].Defined()) - Env->ThrowError("FFmpegSource: No source specified"); - - const char *Source = Args[0].AsString(); - int VTrack = Args[1].AsInt(-1); - int ATrack = Args[2].AsInt(-2); - const char *Timecodes = Args[3].AsString(""); - bool VCache = Args[4].AsBool(true); - const char *VCacheFile = Args[5].AsString(""); - const char *ACacheFile = Args[6].AsString(""); - int ACCompression = Args[7].AsInt(-1); - const char *PPString = Args[8].AsString(""); - int PPQuality = Args[9].AsInt(PP_QUALITY_MAX); - int SeekMode = Args[10].AsInt(1); - - if (VTrack <= -2 && ATrack <= -2) - Env->ThrowError("FFmpegSource: No tracks selected"); - - if (ACCompression < -1 || ACCompression > 8) - Env->ThrowError("FFmpegSource: Invalid audio cache compression selected"); - - AVFormatContext *FormatContext; - - if (av_open_input_file(&FormatContext, Source, NULL, 0, NULL) != 0) - Env->ThrowError("FFmpegSource: Couldn't open %s", Args[0].AsString()); - bool IsMatroska = !strcmp(FormatContext->iformat->name, "matroska"); - av_close_input_file(FormatContext); - - if (IsMatroska) - return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, Env); - else - return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, SeekMode, Env); -} - -AVSValue __cdecl CreateFFPP(AVSValue Args, void* UserData, IScriptEnvironment* Env) { - return new FFPP(Args[0].AsClip(), Args[1].AsString(""), Args[2].AsInt(PP_QUALITY_MAX), Env); -} - -extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) { - Env->AddFunction("FFmpegSource", "[source]s[vtrack]i[atrack]i[timecodes]s[vcache]b[vcachefile]s[acachefile]s[accompression]i[pp]s[ppquality]i[seekmode]i", CreateFFmpegSource, 0); - Env->AddFunction("FFPP", "c[pp]s[ppquality]i", CreateFFPP, 0); - return "FFmpegSource"; -}; diff --git a/FFmpegSource/ffmpegsource.cpp b/FFmpegSource/ffmpegsource.cpp index 0f19c8726..a545bb2c1 100644 --- a/FFmpegSource/ffmpegsource.cpp +++ b/FFmpegSource/ffmpegsource.cpp @@ -126,8 +126,9 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack // Needs to be indexed? if (!ACacheIsValid || !VCacheIsValid) { - +#ifdef FLAC_CACHE FLAC__StreamEncoder *FSE = NULL; +#endif // FLAC_CACHE FILE *RawCache = NULL; if (!ACacheIsValid) if (AACCompression >= 0) @@ -136,7 +137,9 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack AudioCacheType = acRaw; switch (AudioCacheType) { +#ifdef FLAC_CACHE case acFLAC: FSE = NewFLACCacheWriter(AAudioCache, ASource, AudioTrack, AACCompression, Env); break; +#endif // FLAC_CACHE case acRaw: RawCache = NewRawCacheWriter(AAudioCache, ASource, AudioTrack, Env); break; } @@ -161,12 +164,14 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack Data += Ret; VI.num_audio_samples += DecodedSamples; - if (AudioCacheType == acFLAC) { + if (AudioCacheType == acRaw) { + fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache); +#ifdef FLAC_CACHE + } else if (AudioCacheType == acFLAC) { for (int i = 0; i < DecodedSamples * VI.nchannels; i++) FLACBuffer[i] = ((int16_t *)DecodingBuffer)[i]; - FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples); - } else if (AudioCacheType == acRaw) { - fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache); + FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples); +#endif // FLAC_CACHE } } } @@ -176,7 +181,9 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack if (!ACacheIsValid) { switch (AudioCacheType) { +#ifdef FLAC_CACHE case acFLAC: CloseFLACCacheWriter(FSE); break; +#endif // FLAC_CACHE case acRaw: CloseRawCacheWriter(RawCache); break; } @@ -249,7 +256,7 @@ Done: return Ret; } -PVideoFrame __stdcall FFmpegSource::GetFrame(int n, IScriptEnvironment* Env) { +PVideoFrame FFmpegSource::GetFrame(int n, IScriptEnvironment* Env) { bool HasSeeked = false; int ClosestKF = FindClosestKeyFrame(n); diff --git a/FFmpegSource/ffmpegsource.h b/FFmpegSource/ffmpegsource.h index 6ea1fe29a..561ac0114 100644 --- a/FFmpegSource/ffmpegsource.h +++ b/FFmpegSource/ffmpegsource.h @@ -1,3 +1,28 @@ +// Copyright (c) 2007 Fredrik Mellbin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef FFMPEGSOURCE_H +#define FFMPEGSOURCE_H + +#define FLAC_CACHE + #include #include #include @@ -7,14 +32,18 @@ #include #include +#ifdef FLAC_CACHE #include #include +#endif // FLAC_CACHE extern "C" { #include #include #include #include + +#include "stdiostream.h" } #include "MatroskaParser.h" @@ -50,12 +79,15 @@ private: protected: VideoInfo VI; AVFrame *DecodeFrame; - FILE *RawAudioCache; - FLAC__StreamDecoder *FLACAudioCache; AudioCacheFormat AudioCacheType; + FILE *RawAudioCache; + +#ifdef FLAC_CACHE + FLAC__StreamDecoder *FLACAudioCache; + FLAC__int32 *FLACBuffer; +#endif // FLAC_CACHE uint8_t *DecodingBuffer; - FLAC__int32 *FLACBuffer; struct FrameInfo { int64_t DTS; @@ -73,8 +105,10 @@ protected: bool SaveTimecodesToFile(const char *ATimecodeFile, int64_t ScaleD, int64_t ScaleN); bool OpenAudioCache(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env); +#ifdef FLAC_CACHE FLAC__StreamEncoder *FFBase::NewFLACCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, int ACompression, IScriptEnvironment *Env); void FFBase::CloseFLACCacheWriter(FLAC__StreamEncoder *AFSE); +#endif // FLAC_CACHE FILE *FFBase::NewRawCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env); void FFBase::CloseRawCacheWriter(FILE *ARawCache); @@ -113,3 +147,26 @@ public: ~FFmpegSource(); PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env); }; + +class FFMatroskaSource : public FFBase { +private: + StdIoStream ST; + unsigned int BufferSize; + CompressedStream *VideoCS; + CompressedStream *AudioCS; + AVCodecContext *VideoCodecContext; + MatroskaFile *MF; + char ErrorMessage[256]; + uint8_t *Buffer; + int CurrentFrame; + + int ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, CompressedStream *ACS, IScriptEnvironment *Env); + int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, IScriptEnvironment* Env); + int GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env); +public: + FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, int AACCompression, const char *APPString, int AQuality, IScriptEnvironment* Env); + ~FFMatroskaSource(); + PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env); +}; + +#endif \ No newline at end of file diff --git a/FFmpegSource/ffmpegsource.html b/FFmpegSource/ffmpegsource.html index 3d963bb20..c7d7a2ce9 100644 --- a/FFmpegSource/ffmpegsource.html +++ b/FFmpegSource/ffmpegsource.html @@ -11,9 +11,12 @@ FFmpegSource Documentation
  • 1.11
    • Now officially uses the MIT license
    • +
    • Much cleaner source
    • +
    • Can be compiled without support for compressing the audio cache with FLAC
    • Supports more audio formats in matroska
    • -
    • RGB24 output no longer has swapped colors if the video is converted to it for output
    • +
    • RGB24 output no longer has swapped colors if the video is converted to it for output (there still seems to be some bugs lurking when conversion is done with libswscale)
    • Fixed an access violation on close when no audio is opened (introduced in 1.10)
    • +
    • Updated FFmpeg to rev 10423
  • 1.10
      @@ -222,7 +225,9 @@ tn:64:128:256

      FFmpeg svn from http://ffmpeg.mplayerhq.hu/

      -

      Required Configuration: +

      FLAC (optional) from http://flac.sourceforge.net/

      + +

      Required FFmpeg Configuration: ./configure --enable-shared --disable-static --enable-memalign-hack --enable-gpl --enable-swscaler

      Suggested Additional Options: diff --git a/FFmpegSource/ffpp.cpp b/FFmpegSource/ffpp.cpp index 6eaaf1127..e8701241b 100644 --- a/FFmpegSource/ffpp.cpp +++ b/FFmpegSource/ffpp.cpp @@ -70,7 +70,7 @@ FFPP::~FFPP() { avpicture_free(&OutputPicture); } -PVideoFrame __stdcall FFPP::GetFrame(int n, IScriptEnvironment* Env) { +PVideoFrame FFPP::GetFrame(int n, IScriptEnvironment* Env) { PVideoFrame Src = child->GetFrame(n, Env); PVideoFrame Dst = Env->NewVideoFrame(vi); diff --git a/FFmpegSource/ffshared.cpp b/FFmpegSource/ffshared.cpp index 1ebf6fbd6..5db95c924 100644 --- a/FFmpegSource/ffshared.cpp +++ b/FFmpegSource/ffshared.cpp @@ -46,4 +46,59 @@ int GetSWSCPUFlags(IScriptEnvironment *Env) { CPUFlags |= SWS_CPU_CAPS_3DNOW; return Flags; -} \ No newline at end of file +} + +AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) { + if (!UserData) { + av_register_all(); + UserData = (void *)-1; + } + + if (!Args[0].Defined()) + Env->ThrowError("FFmpegSource: No source specified"); + + const char *Source = Args[0].AsString(); + int VTrack = Args[1].AsInt(-1); + int ATrack = Args[2].AsInt(-2); + const char *Timecodes = Args[3].AsString(""); + bool VCache = Args[4].AsBool(true); + const char *VCacheFile = Args[5].AsString(""); + const char *ACacheFile = Args[6].AsString(""); + int ACCompression = Args[7].AsInt(-1); + const char *PPString = Args[8].AsString(""); + int PPQuality = Args[9].AsInt(PP_QUALITY_MAX); + int SeekMode = Args[10].AsInt(1); + + if (VTrack <= -2 && ATrack <= -2) + Env->ThrowError("FFmpegSource: No tracks selected"); + +#ifdef FLAC_CACHE + if (ACCompression < -1 || ACCompression > 8) +#else + if (ACCompression != -1) +#endif // FLAC_CACHE + Env->ThrowError("FFmpegSource: Invalid audio cache compression selected"); + + + AVFormatContext *FormatContext; + + if (av_open_input_file(&FormatContext, Source, NULL, 0, NULL) != 0) + Env->ThrowError("FFmpegSource: Couldn't open %s", Args[0].AsString()); + bool IsMatroska = !strcmp(FormatContext->iformat->name, "matroska"); + av_close_input_file(FormatContext); + + if (IsMatroska) + return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, Env); + else + return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, SeekMode, Env); +} + +AVSValue __cdecl CreateFFPP(AVSValue Args, void* UserData, IScriptEnvironment* Env) { + return new FFPP(Args[0].AsClip(), Args[1].AsString(""), Args[2].AsInt(PP_QUALITY_MAX), Env); +} + +extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) { + Env->AddFunction("FFmpegSource", "[source]s[vtrack]i[atrack]i[timecodes]s[vcache]b[vcachefile]s[acachefile]s[accompression]i[pp]s[ppquality]i[seekmode]i", CreateFFmpegSource, 0); + Env->AddFunction("FFPP", "c[pp]s[ppquality]i", CreateFFPP, 0); + return "FFmpegSource"; +}; diff --git a/FFmpegSource/stdiostream.c b/FFmpegSource/stdiostream.c index 98200e533..97988a90f 100644 --- a/FFmpegSource/stdiostream.c +++ b/FFmpegSource/stdiostream.c @@ -1,6 +1,24 @@ -#include "stdiostream.h" +// Copyright (c) 2007 Fredrik Mellbin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. -#define CACHESIZE 65536 +#include "stdiostream.h" /* StdIoStream methods */ diff --git a/FFmpegSource/stdiostream.h b/FFmpegSource/stdiostream.h index 3a5fc35db..4a383cf11 100644 --- a/FFmpegSource/stdiostream.h +++ b/FFmpegSource/stdiostream.h @@ -1,14 +1,40 @@ +// Copyright (c) 2007 Fredrik Mellbin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + #ifndef STDIOSTREAM_H #define STDIOSTREAM_H +#include +#include +#include +#include +#include +#include #include "MatroskaParser.h" +#define CACHESIZE 65536 /************\ * Structures * \************/ - /* first we need to create an I/O object that the parser will use to read the * source file */ @@ -20,8 +46,6 @@ struct StdIoStream { typedef struct StdIoStream StdIoStream; - - /***********\ * Functions * \***********/