diff --git a/FFmpegSource/ffaudiobase.cpp b/FFmpegSource/ffaudiobase.cpp index 57f6bbea8..e29295aa0 100644 --- a/FFmpegSource/ffaudiobase.cpp +++ b/FFmpegSource/ffaudiobase.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 diff --git a/FFmpegSource/ffbase.cpp b/FFmpegSource/ffbase.cpp index 67c296caf..fc4799fd1 100644 --- a/FFmpegSource/ffbase.cpp +++ b/FFmpegSource/ffbase.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 @@ -29,7 +29,7 @@ int FFBase::FrameFromDTS(int64_t ADTS) { int FFBase::ClosestFrameFromDTS(int64_t ADTS) { int Frame = 0; - int64_t BestDiff = 0xFFFFFFFFFFFFFFLL; + int64_t BestDiff = 0xFFFFFFFFFFFFFFLL; // big number for (int i = 0; i < (int)Frames.size(); i++) { int64_t CurrentDiff = FFABS(Frames[i].DTS - ADTS); if (CurrentDiff < BestDiff) { @@ -113,83 +113,6 @@ 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); - if(ferror(AOwner->FCFile)) - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - else if(*ABytes == 0) - return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - else - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; - } else { - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - } -} - -static FLAC__StreamDecoderSeekStatus FLACStreamDecoderSeekCallback(const FLAC__StreamDecoder *ADecoder, FLAC__uint64 AAbsoluteByteOffset, FFBase *AOwner) { - if(_fseeki64(AOwner->FCFile, AAbsoluteByteOffset, SEEK_SET) < 0) - return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; - else - return FLAC__STREAM_DECODER_SEEK_STATUS_OK; -} - -static FLAC__StreamDecoderTellStatus FLACStreamDecoderTellCallback(const FLAC__StreamDecoder *ADecoder, FLAC__uint64 *AAbsoluteByteOffset, FFBase *AOwner) { - __int64 Pos; - if ((Pos = _ftelli64(AOwner->FCFile)) < 0) { - return FLAC__STREAM_DECODER_TELL_STATUS_ERROR; - } else { - *AAbsoluteByteOffset = (FLAC__uint64)Pos; - return FLAC__STREAM_DECODER_TELL_STATUS_OK; - } -} - -static FLAC__StreamDecoderLengthStatus FLACStreamDecoderLengthCallback(const FLAC__StreamDecoder *ADecoder, FLAC__uint64 *AStreamLength, FFBase *AOwner) { - __int64 OriginalPos; - __int64 Length; - if ((OriginalPos = _ftelli64(AOwner->FCFile)) < 0) - return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; - _fseeki64(AOwner->FCFile, 0, SEEK_END); - if ((Length = _ftelli64(AOwner->FCFile)) < 0) - return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR; - _fseeki64(AOwner->FCFile, OriginalPos, SEEK_SET); - *AStreamLength = Length; - return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; -} - -static FLAC__bool FLACStreamDecoderEofCallback(const FLAC__StreamDecoder *ADecoder, FFBase *AOwner) { - return feof(AOwner->FCFile) ? true : false; -} - -static FLAC__StreamDecoderWriteStatus FLACStreamDecoderWriteCallback(const FLAC__StreamDecoder *ADecoder, const FLAC__Frame *AFrame, const FLAC__int32 *const ABuffer[], FFBase *AOwner) { - unsigned Blocksize = AFrame->header.blocksize; - const VideoInfo VI = AOwner->GetVideoInfo(); - int16_t *Buffer = (int16_t *)AOwner->FCBuffer; - - int j = 0; - while (AOwner->FCCount > 0 && Blocksize > 0) { - for (int i = 0; i < VI.nchannels; i++) - *Buffer++ = ABuffer[i][j]; - j++; - AOwner->FCCount--; - Blocksize--; - } - - AOwner->FCBuffer = Buffer; - - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; -} - -static void FLACStreamDecoderMetadataCallback(const FLAC__StreamDecoder *ADecoder, const FLAC__StreamMetadata *AMetadata, FFBase *AOwner) { - AOwner->FCError = (AMetadata->data.stream_info.total_samples <= 0); -} - -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]; sprintf(DefaultCacheFilename, "%s.ffa%dcache", ASource, AAudioTrack); @@ -197,7 +120,7 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in AAudioCacheFile = DefaultCacheFilename; // Is an empty file? - FCFile = fopen(AAudioCacheFile, "rb"); + FILE *FCFile = fopen(AAudioCacheFile, "rb"); int64_t CacheSize; if (FCFile) { _fseeki64(FCFile, 0, SEEK_END); @@ -212,29 +135,6 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in return false; } -#ifdef FLAC_CACHE - // is FLAC? - FLACAudioCache = FLAC__stream_decoder_new(); - if (FLAC__stream_decoder_init_stream(FLACAudioCache, - &(FLAC__StreamDecoderReadCallback)FLACStreamDecoderReadCallback, - &(FLAC__StreamDecoderSeekCallback)FLACStreamDecoderSeekCallback, - &(FLAC__StreamDecoderTellCallback)FLACStreamDecoderTellCallback, - &(FLAC__StreamDecoderLengthCallback)FLACStreamDecoderLengthCallback, - &(FLAC__StreamDecoderEofCallback)FLACStreamDecoderEofCallback, - &(FLAC__StreamDecoderWriteCallback)FLACStreamDecoderWriteCallback, - &(FLAC__StreamDecoderMetadataCallback)FLACStreamDecoderMetadataCallback, &(FLAC__StreamDecoderErrorCallback)FLACStreamDecoderErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK) { - FCError = true; - FLAC__stream_decoder_process_until_end_of_metadata(FLACAudioCache); - if (!FCError) { - VI.num_audio_samples = FLAC__stream_decoder_get_total_samples(FLACAudioCache); - AudioCacheType = acFLAC; - return true; - } - } - FLAC__stream_decoder_delete(FLACAudioCache); - FLACAudioCache = NULL; -#endif // FLAC_CACHE - // Raw audio VI.num_audio_samples = VI.AudioSamplesFromBytes(CacheSize); AudioCacheType = acRaw; @@ -243,64 +143,6 @@ 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)) - return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; - else - return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; -} - -static FLAC__StreamEncoderSeekStatus FLACStreamEncoderSeekCallback(const FLAC__StreamEncoder *AEncoder, FLAC__uint64 AAbsoluteByteOffset, FFBase *AOwner) { - if(_fseeki64(AOwner->FCFile, AAbsoluteByteOffset, SEEK_SET) < 0) - return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR; - else - return FLAC__STREAM_ENCODER_SEEK_STATUS_OK; -} - -static FLAC__StreamEncoderTellStatus FLACStreamEncoderTellCallback(const FLAC__StreamEncoder *AEncoder, FLAC__uint64 *AAbsoluteByteOffset, FFBase *AOwner) { - __int64 Pos; - if((Pos = _ftelli64(AOwner->FCFile)) < 0) { - return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR; - } else { - *AAbsoluteByteOffset = (FLAC__uint64)Pos; - return FLAC__STREAM_ENCODER_TELL_STATUS_OK; - } -} - -FLAC__StreamEncoder *FFBase::NewFLACCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, int ACompression, IScriptEnvironment *Env) { - char DefaultCacheFilename[1024]; - sprintf(DefaultCacheFilename, "%s.ffa%dcache", ASource, AAudioTrack); - if (!strcmp(AAudioCacheFile, "")) - AAudioCacheFile = DefaultCacheFilename; - - FCFile = fopen(AAudioCacheFile, "wb"); - if (!FCFile) - Env->ThrowError("FFmpegSource: Failed to open '%s' for writing", AAudioCacheFile); - FLAC__StreamEncoder *FSE; - FSE = FLAC__stream_encoder_new(); - FLAC__stream_encoder_set_channels(FSE, VI.nchannels); - FLAC__stream_encoder_set_bits_per_sample(FSE, VI.BytesPerChannelSample() * 8); - FLAC__stream_encoder_set_sample_rate(FSE, VI.audio_samples_per_second); - FLAC__stream_encoder_set_compression_level(FSE, ACompression); - if (FLAC__stream_encoder_init_stream(FSE, &(FLAC__StreamEncoderWriteCallback)FLACStreamEncoderWriteCallback, - &(FLAC__StreamEncoderSeekCallback)FLACStreamEncoderSeekCallback, - &(FLAC__StreamEncoderTellCallback)FLACStreamEncoderTellCallback, NULL, this) - != FLAC__STREAM_ENCODER_INIT_STATUS_OK) - Env->ThrowError("FFmpegSource: Failed to initialize the FLAC encoder for '%s'", AAudioCacheFile); - - return FSE; -} - -void FFBase::CloseFLACCacheWriter(FLAC__StreamEncoder *AFSE) { - FLAC__stream_encoder_finish(AFSE); - FLAC__stream_encoder_delete(AFSE); - fclose(FCFile); - FCFile = NULL; -} -#endif // FLAC_CACHE - FILE *FFBase::NewRawCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env) { char DefaultCacheFilename[1024]; sprintf(DefaultCacheFilename, "%s.ffa%dcache", ASource, AAudioTrack); @@ -325,7 +167,7 @@ void FFBase::InitPP(int AWidth, int AHeight, const char *APPString, int AQuality Env->ThrowError("FFmpegSource: Quality is out of range"); // Unsafe? - PPMode = pp_get_mode_by_name_and_quality((char *)APPString, AQuality); + PPMode = pp_get_mode_by_name_and_quality(APPString, AQuality); if (!PPMode) Env->ThrowError("FFmpegSource: Invalid postprocesing settings"); @@ -379,7 +221,7 @@ PVideoFrame FFBase::OutputFrame(AVFrame *AFrame, IScriptEnvironment *Env) { AVPicture *SrcPicture = (AVPicture *)AFrame; if (PPContext) { - pp_postprocess(AFrame->data, AFrame->linesize, PPPicture.data, PPPicture.linesize, VI.width, VI.height, AFrame->qscale_table, AFrame->qstride, PPMode, PPContext, AFrame->pict_type | (AFrame->qscale_type ? PP_PICT_TYPE_QP2 : 0)); + pp_postprocess(const_cast(AFrame->data), AFrame->linesize, PPPicture.data, PPPicture.linesize, VI.width, VI.height, AFrame->qscale_table, AFrame->qstride, PPMode, PPContext, AFrame->pict_type | (AFrame->qscale_type ? PP_PICT_TYPE_QP2 : 0)); SrcPicture = &PPPicture; } @@ -416,15 +258,7 @@ PVideoFrame FFBase::OutputFrame(AVFrame *AFrame, 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, (size_t)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 + fread(Buf, 1, static_cast(VI.BytesFromAudioSamples(Count)), RawAudioCache); } else { Env->ThrowError("FFmpegSource: Audio requested but none available"); } @@ -433,18 +267,12 @@ void FFBase::GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironmen FFBase::FFBase() { memset(&VI, 0, sizeof(VI)); AudioCacheType = acNone; - FCError = false; RawAudioCache = NULL; PPContext = NULL; PPMode = NULL; SWS = NULL; LastFrameNum = -1; 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)); DecodeFrame = avcodec_alloc_frame(); @@ -454,15 +282,6 @@ FFBase::~FFBase() { delete [] DecodingBuffer; 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) sws_freeContext(SWS); if (PPMode) diff --git a/FFmpegSource/ffmatroskaaudiosource.cpp b/FFmpegSource/ffmatroskaaudiosource.cpp index 5b08ed5ca..aaead6a2b 100644 --- a/FFmpegSource/ffmatroskaaudiosource.cpp +++ b/FFmpegSource/ffmatroskaaudiosource.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 diff --git a/FFmpegSource/ffmatroskasource.cpp b/FFmpegSource/ffmatroskasource.cpp index 5cfa626f2..2b3a497fa 100644 --- a/FFmpegSource/ffmatroskasource.cpp +++ b/FFmpegSource/ffmatroskasource.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 @@ -45,8 +45,8 @@ int FFMatroskaSource::GetTrackIndex(int Index, unsigned char ATrackType, IScript } 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, FrameInfoVector *AFrames) { + bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, + int AQuality, int AThreads, IScriptEnvironment* Env, FrameInfoVector *AFrames) { AFrames = &Frames; CurrentFrame = 0; @@ -105,6 +105,7 @@ FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAu VideoCodecContext = avcodec_alloc_context(); VideoCodecContext->extradata = (uint8_t *)VideoTI->CodecPrivate; VideoCodecContext->extradata_size = VideoTI->CodecPrivateSize; + VideoCodecContext->thread_count = AThreads; VideoCodec = avcodec_find_decoder(MatroskaToFFCodecID(VideoTI)); if (VideoCodec == NULL) @@ -184,11 +185,11 @@ FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAu 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_U8: VI.sample_type = SAMPLE_INT8; 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; + case SAMPLE_FMT_S24: VI.sample_type = SAMPLE_INT24; break; + case SAMPLE_FMT_S32: VI.sample_type = SAMPLE_INT32; break; + case SAMPLE_FMT_FLT: VI.sample_type = SAMPLE_FLOAT; break; default: Env->ThrowError("FFmpegSource: Unsupported/unknown sample format"); } @@ -202,20 +203,11 @@ FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAu // 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; + 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; } @@ -244,21 +236,12 @@ FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAu 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 } } } if (!ACacheIsValid) { switch (AudioCacheType) { -#ifdef FLAC_CACHE - case acFLAC: CloseFLACCacheWriter(FSE); break; -#endif // FLAC_CACHE case acRaw: CloseRawCacheWriter(RawCache); break; } diff --git a/FFmpegSource/ffmpegaudiosource.cpp b/FFmpegSource/ffmpegaudiosource.cpp index b9816118f..aa8fa7348 100644 --- a/FFmpegSource/ffmpegaudiosource.cpp +++ b/FFmpegSource/ffmpegaudiosource.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 diff --git a/FFmpegSource/ffmpegsource.cpp b/FFmpegSource/ffmpegsource.cpp index 30d7316ef..fee4359ce 100644 --- a/FFmpegSource/ffmpegsource.cpp +++ b/FFmpegSource/ffmpegsource.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 @@ -45,8 +45,8 @@ int FFmpegSource::GetTrackIndex(int Index, CodecType ATrackType, IScriptEnvironm FFmpegSource::FFmpegSource(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, int ASeekMode, IScriptEnvironment *Env, FrameInfoVector *AFrames) { + bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, + int AQuality, int AThreads, int ASeekMode, IScriptEnvironment *Env, FrameInfoVector *AFrames) { AFrames = &Frames; CurrentFrame = 0; @@ -79,6 +79,7 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack VCacheIsValid = LoadFrameInfoFromFile(AVideoCache, ASource, VideoTrack); VideoCodecContext = FormatContext->streams[VideoTrack]->codec; + VideoCodecContext->thread_count = AThreads; VideoCodec = avcodec_find_decoder(VideoCodecContext->codec_id); if (VideoCodec == NULL) @@ -124,11 +125,11 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack 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_U8: VI.sample_type = SAMPLE_INT8; 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; + case SAMPLE_FMT_S24: VI.sample_type = SAMPLE_INT24; break; + case SAMPLE_FMT_S32: VI.sample_type = SAMPLE_INT32; break; + case SAMPLE_FMT_FLT: VI.sample_type = SAMPLE_FLOAT; break; default: Env->ThrowError("FFmpegSource: Unsupported/unknown sample format"); } @@ -144,20 +145,11 @@ 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) - AudioCacheType = acFLAC; - else - AudioCacheType = acRaw; + 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; } @@ -184,12 +176,6 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack 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 } } } @@ -199,9 +185,6 @@ 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; } diff --git a/FFmpegSource/ffmpegsource.h b/FFmpegSource/ffmpegsource.h index a3de98b6e..d201da622 100644 --- a/FFmpegSource/ffmpegsource.h +++ b/FFmpegSource/ffmpegsource.h @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 @@ -21,10 +21,6 @@ #ifndef FFMPEGSOURCE_H #define FFMPEGSOURCE_H -#ifndef NO_FLAC_CACHE -//#define FLAC_CACHE -#endif - #include #include #include @@ -35,16 +31,11 @@ #include #include -#ifdef FLAC_CACHE -#include -#include -#endif // FLAC_CACHE - extern "C" { -#include -#include -#include -#include +#include +#include +#include +#include #include "stdiostream.h" } @@ -52,7 +43,7 @@ extern "C" { #include "MatroskaParser.h" #include "avisynth.h" -enum AudioCacheFormat {acNone, acRaw, acFLAC}; +enum AudioCacheFormat {acNone, acRaw}; struct FrameInfo { int64_t DTS; @@ -111,11 +102,6 @@ protected: int LastFrameNum; uint8_t *DecodingBuffer; -#ifdef FLAC_CACHE - FLAC__StreamDecoder *FLACAudioCache; - FLAC__int32 *FLACBuffer; -#endif // FLAC_CACHE - FrameInfoVector Frames; int FindClosestKeyFrame(int AFrame); @@ -126,10 +112,6 @@ 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); @@ -137,11 +119,6 @@ protected: void SetOutputFormat(int ACurrentFormat, IScriptEnvironment *Env); PVideoFrame OutputFrame(AVFrame *AFrame, IScriptEnvironment *Env); public: - // FLAC decoder variables, have to be public - FILE *FCFile; - __int64 FCCount; - void *FCBuffer; - bool FCError; FFBase(); ~FFBase(); @@ -164,7 +141,7 @@ private: int GetTrackIndex(int Index, CodecType ATrackType, IScriptEnvironment *Env); int DecodeNextFrame(AVFrame *Frame, int64_t *DTS); public: - FFmpegSource(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, int ASeekMode, IScriptEnvironment *Env, FrameInfoVector *AFrames); + FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, int AQuality, int AThreads, int ASeekMode, IScriptEnvironment *Env, FrameInfoVector *AFrames); ~FFmpegSource(); PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env); }; @@ -185,7 +162,7 @@ private: 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, FrameInfoVector *AFrames); + FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, int AQuality, int AThreads, IScriptEnvironment *Env, FrameInfoVector *AFrames); ~FFMatroskaSource(); PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env); }; diff --git a/FFmpegSource/ffmpegsource.html b/FFmpegSource/ffmpegsource.html index eff59ee22..e32379c32 100644 --- a/FFmpegSource/ffmpegsource.html +++ b/FFmpegSource/ffmpegsource.html @@ -28,7 +28,7 @@ Loads video files without sucking

Usage

-FFmpegSource(string source, int vtrack = -1, int atrack = -2, string timecodes, bool vcache = true, string vcachefile, string acachefile, int accompression = -1, string pp, int ppquality = 6, int seekmode = 1)
+FFmpegSource(string source, int vtrack = -1, int atrack = -2, string timecodes, bool vcache = true, string vcachefile, string acachefile, string pp, int ppquality = 6, int threads = 1, int seekmode = 1)

@@ -45,7 +45,7 @@ Experimental, may or may not be accurate enough for real usage.

FFPP(clip, string pp, int ppquality = 6)
-Separate postprocessing which also seems to include a few simple deinterlacers + Separate postprocessing which also seems to include a few simple deinterlacers

@@ -79,14 +79,9 @@ Separate postprocessing which also seems to include a few simple deinterlacers Specifies the file to store the demuxed audio stream in. Only used by FFAudioSource if the stream isn't matroska. If nothing is specified (source).ffasd(tracknumber)cache is used.

-

-accompression: - Audio cache compression, -1 means raw audio and 0-8 uses FLAC with that compression level. -

-

pp: - See the table below for a full description, an empty string means no processing. It is recommended to avoid the autoq option since it's currently unknown what effect it will have on the processing. + See the table below for a full description, an empty string means no processing. It is recommended to avoid the autoq option since it's currently unknown what effect it will have on the processing.

@@ -94,6 +89,11 @@ Separate postprocessing which also seems to include a few simple deinterlacers The quality to use for the specified postprocessing. Valid values are 0-6 where 0 usually means that no actual processing is done.

+

+threads: + Sets the number of decoder threads used, ignored if the used decoder doesn't implement it. +

+

seekmode: Force how seeking is handled, has no effect on matroska files which always use the equivalent of seekmode=1
@@ -154,16 +154,32 @@ tn:64:128:256

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

-

FLAC (optional) from http://flac.sourceforge.net/ (static library seems to be broken)

-

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

+./configure --enable-memalign-hack --enable-gpl --enable-swscale --enable-postproc

Suggested Additional Options: ---disable-encoders --disable-muxers --enable-small

+--enable-w32threads --disable-encoders --disable-muxers --enable-small --enable-libfaad --disable-debug

+

+Note that --enable-w32threads is required for multithreaded decoding to work. +

Changes

    +
  • 1.17
      +
    • Updated FFmpeg to rev X
    • +
  • + +
  • 1.16
      +
    • Added many new and missing matroska codec ids
    • +
    • Added threads argument to set the number of decoding threads used
    • +
    • Completely removed FLAC cache
    • +
    • Updated FFmpeg to rev 12382
    • +
  • + +
  • 1.15
      +
    • Updated FFmpeg to rev 11518
    • +
  • +
  • 1.14
    • If the output colorspace is YV12 or YUY2 the width and height may be automatically cropped by one pixel to make it an even number
    • FLAC cache is disabled because the static FLAC lib doesn't want to link
    • @@ -172,8 +188,6 @@ tn:64:128:256
    • Updated FFmpeg to rev 11413
  • -

    Changes

    -
    • 1.13
      • Now always sorts the output timecodes so native avc in mkv won't have out of order values
      • Fixed the missing '# timecode format v2' line in saved timecode files
      • diff --git a/FFmpegSource/ffpp.cpp b/FFmpegSource/ffpp.cpp index f77479d59..4fd9b35f1 100644 --- a/FFmpegSource/ffpp.cpp +++ b/FFmpegSource/ffpp.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 @@ -75,7 +75,7 @@ PVideoFrame FFPP::GetFrame(int n, IScriptEnvironment* Env) { PVideoFrame Dst = Env->NewVideoFrame(vi); if (vi.IsYV12()) { - uint8_t *SrcData[3] = {(uint8_t *)Src->GetReadPtr(PLANAR_Y), (uint8_t *)Src->GetReadPtr(PLANAR_U), (uint8_t *)Src->GetReadPtr(PLANAR_V)}; + const uint8_t *SrcData[3] = {(uint8_t *)Src->GetReadPtr(PLANAR_Y), (uint8_t *)Src->GetReadPtr(PLANAR_U), (uint8_t *)Src->GetReadPtr(PLANAR_V)}; int SrcStride[3] = {Src->GetPitch(PLANAR_Y), Src->GetPitch(PLANAR_U), Src->GetPitch(PLANAR_V)}; uint8_t *DstData[3] = {Dst->GetWritePtr(PLANAR_Y), Dst->GetWritePtr(PLANAR_U), Dst->GetWritePtr(PLANAR_V)}; int DstStride[3] = {Dst->GetPitch(PLANAR_Y), Dst->GetPitch(PLANAR_U), Dst->GetPitch(PLANAR_V)}; @@ -86,7 +86,7 @@ PVideoFrame FFPP::GetFrame(int n, IScriptEnvironment* Env) { int SrcStride[1] = {Src->GetPitch()}; sws_scale(SWSTo422P, SrcData, SrcStride, 0, vi.height, InputPicture.data, InputPicture.linesize); - pp_postprocess(InputPicture.data, InputPicture.linesize, OutputPicture.data, OutputPicture.linesize, vi.width, vi.height, NULL, 0, PPMode, PPContext, 0); + pp_postprocess(const_cast(InputPicture.data), InputPicture.linesize, OutputPicture.data, OutputPicture.linesize, vi.width, vi.height, NULL, 0, PPMode, PPContext, 0); uint8_t *DstData[1] = {Dst->GetWritePtr()}; int DstStride[1] = {Dst->GetPitch()}; diff --git a/FFmpegSource/ffshared.cpp b/FFmpegSource/ffshared.cpp index ad3e272c8..87ddea0ae 100644 --- a/FFmpegSource/ffshared.cpp +++ b/FFmpegSource/ffshared.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 @@ -64,9 +64,9 @@ AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnviro 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); + const char *PPString = Args[7].AsString(""); + int PPQuality = Args[8].AsInt(PP_QUALITY_MAX); + int Threads = Args[9].AsInt(1); int SeekMode = Args[10].AsInt(1); if (VTrack <= -2 && ATrack <= -2) @@ -75,13 +75,8 @@ AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnviro if (SeekMode < -1 || SeekMode > 3) Env->ThrowError("FFmpegSource: Invalid seekmode selected"); -#ifdef FLAC_CACHE - if (ACCompression < -1 || ACCompression > 8) -#else - if (ACCompression != -1) -#endif // FLAC_CACHE - Env->ThrowError("FFmpegSource: Invalid audio cache compression selected"); - + if (Threads < 1) + Env->ThrowError("FFmpegSource: Invalid thread count"); AVFormatContext *FormatContext; @@ -93,12 +88,12 @@ AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnviro FrameInfoVector Frames; if (IsMatroska) { - return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, Env, &Frames); + return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, Env, &Frames); } else { // Do a separate indexing pass, enjoy the constructor sideeffects if (SeekMode == -1) - delete new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, -2, Env, &Frames); - return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, SeekMode, Env, &Frames); + delete new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, -2, Env, &Frames); + return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, SeekMode, Env, &Frames); } } @@ -138,7 +133,7 @@ AVSValue __cdecl CreateFFPP(AVSValue Args, void* UserData, IScriptEnvironment* E } 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("FFmpegSource", "[source]s[vtrack]i[atrack]i[timecodes]s[vcache]b[vcachefile]s[acachefile]s[pp]s[ppquality]i[threads]i[seekmode]i", CreateFFmpegSource, 0); Env->AddFunction("FFAudioSource", "[source]s[atrack]i[acachefile]s[ademuxedfile]s", CreateFFAudioSource, 0); Env->AddFunction("FFPP", "c[pp]s[ppquality]i", CreateFFPP, 0); return "FFmpegSource"; diff --git a/FFmpegSource/matroskacodecs.cpp b/FFmpegSource/matroskacodecs.cpp index 78d9d5b45..02eae335d 100644 --- a/FFmpegSource/matroskacodecs.cpp +++ b/FFmpegSource/matroskacodecs.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 @@ -135,9 +135,9 @@ CodecID MatroskaToFFCodecID(TrackInfo *TI) { case MAKEFOURCC('M', 'S', 'Z', 'H'): return CODEC_ID_MSZH; case MAKEFOURCC('Z', 'L', 'I', 'B'): - return CODEC_ID_FLV1; - case MAKEFOURCC('F', 'L', 'V', '1'): return CODEC_ID_ZLIB; + case MAKEFOURCC('F', 'L', 'V', '1'): + return CODEC_ID_FLV1; /* case MAKEFOURCC('P', 'N', 'G', '1'): return CODEC_ID_COREPNG; @@ -199,18 +199,33 @@ CodecID MatroskaToFFCodecID(TrackInfo *TI) { default: return CODEC_ID_NONE; } + } 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; // bleh + else if (!strcmp(Codec, "V_QUICKTIME")) + return CODEC_ID_SVQ3; + 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': @@ -227,6 +242,8 @@ CodecID MatroskaToFFCodecID(TrackInfo *TI) { /* 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")) @@ -243,8 +260,20 @@ CodecID MatroskaToFFCodecID(TrackInfo *TI) { case 32: return CODEC_ID_PCM_S32LE; default: return CODEC_ID_NONE; } + } else if (!strcmp(Codec, "A_PCM/INT/BIG")) { + 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; + } } else if (!strcmp(Codec, "A_PCM/FLOAT/IEEE")) return CODEC_ID_NONE; // no float codec id? + else if (!strcmp(Codec, "A_FLAC")) + return CODEC_ID_FLAC; + else if (!strcmp(Codec, "A_MPC")) + return CODEC_ID_MUSEPACK8; else if (!strcmp(Codec, "A_TTA1")) return CODEC_ID_TTA; else if (!strcmp(Codec, "A_WAVPACK4")) @@ -263,6 +292,10 @@ CodecID MatroskaToFFCodecID(TrackInfo *TI) { 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? //#include "Mmreg.h" diff --git a/FFmpegSource/stdiostream.c b/FFmpegSource/stdiostream.c index 9f97430ac..b660ff7d1 100644 --- a/FFmpegSource/stdiostream.c +++ b/FFmpegSource/stdiostream.c @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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 diff --git a/FFmpegSource/stdiostream.h b/FFmpegSource/stdiostream.h index 4a383cf11..eaf74d28e 100644 --- a/FFmpegSource/stdiostream.h +++ b/FFmpegSource/stdiostream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2007 Fredrik Mellbin +// Copyright (c) 2007-2008 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