From 400266c383687f06f75bea474dfe1c2880ff0794 Mon Sep 17 00:00:00 2001
From: Fredrik Mellbin
Date: Mon, 30 Jul 2007 11:04:10 +0000
Subject: [PATCH] FFmpegSource 1.6
Originally committed to SVN as r1464.
---
FFmpegSource/ffmpegsource.cpp | 51 ++++++++++++++++++++++++++++++----
FFmpegSource/ffmpegsource.html | 10 +++++++
2 files changed, 55 insertions(+), 6 deletions(-)
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
Changes
+- 1.6
+- Fixed ac3 and other formats stored in mkv
+- Skip unnecessary seeking when index information already exists (gif file opening only 3/4 broken now)
+- Throws an error when the selected audio/video track has no frames/samples
+
+
- 1.5
- Fixed a bug that made avformat opened files only return audio if only the audio cache needed to be created
- Rejects more corrupt cache files
@@ -77,6 +83,10 @@ FFmpegSource Documentation
FFmpegSource(string source, int vtrack = -1, int atrack = -2, string timecodes, bool vcache = true, string vcachefile, string acachefile, string pp, int ppquality = 6, int seekmode = 1)
+
+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