diff --git a/FFmpegSource/ffmpegsource.cpp b/FFmpegSource/ffmpegsource.cpp index 471b6fe7a..6df03ff9f 100644 --- a/FFmpegSource/ffmpegsource.cpp +++ b/FFmpegSource/ffmpegsource.cpp @@ -150,6 +150,33 @@ public: 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; + } + + mkv_Seek(MF, 0, MKVF_SEEK_TO_PREV_KEYFRAME); + } + + 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; break; case SAMPLE_FMT_S16: VI.sample_type = SAMPLE_INT16; break; @@ -160,9 +187,6 @@ public: Env->ThrowError("FFmpegSource: Unsupported/unknown sample format"); } - VI.nchannels = AudioCodecContext->channels; - VI.audio_samples_per_second = AudioCodecContext->sample_rate; - ACacheIsValid = PrepareAudioCache(AAudioCache, ASource, AudioTrack, Env); if (!ACacheIsValid) TrackMask &= ~(1 << AudioTrack); @@ -199,6 +223,15 @@ public: } } + 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"); @@ -211,7 +244,6 @@ public: if (VideoTrack >= 0) { mkv_SetTrackMask(MF, ~(1 << VideoTrack)); - mkv_Seek(MF, FrameToDTS.front().DTS, MKVF_SEEK_TO_PREV_KEYFRAME); if (FrameToDTS.size() >= 2) { double DTSDiff = (double)(FrameToDTS.back().DTS - FrameToDTS.front().DTS); @@ -488,6 +520,15 @@ public: av_free_packet(&Packet); } + 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) + av_seek_frame(FormatContext, VideoTrack, FrameToDTS.front().DTS, AVSEEK_FLAG_BACKWARD); + if (AVCache) if (!SaveFrameInfoToFile(AVideoCache, ASource, VideoTrack)) Env->ThrowError("FFmpegSource: Failed to write video cache info"); @@ -497,8 +538,6 @@ public: avcodec_close(AudioCodecContext); if (VideoTrack >= 0) { - av_seek_frame(FormatContext, VideoTrack, FrameToDTS.front().DTS, AVSEEK_FLAG_BACKWARD); - if (!SaveTimecodesToFile(ATimecodes, FormatContext->streams[VideoTrack]->time_base.num * 1000, FormatContext->streams[VideoTrack]->time_base.den)) Env->ThrowError("FFmpegSource: Failed to write timecodes"); diff --git a/FFmpegSource/ffmpegsource.html b/FFmpegSource/ffmpegsource.html index e6c21eedf..3b4cad107 100644 --- a/FFmpegSource/ffmpegsource.html +++ b/FFmpegSource/ffmpegsource.html @@ -9,6 +9,12 @@ FFmpegSource Documentation
+Note that the audio cache will always be created when opening files with audio and that it will be huge since it stores all audio as raw signed 16 bit pcm. +
+
FFPP(clip, string pp, int ppquality = 6)
Separate postprocessing which also seems to include a few simple deinterlacers