ext/ffmpeg/gstffmpegdec.c: So, stupid ffmpeg.... Not all [en|de]coders set AVFrame->type.

Original commit message from CVS:
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_frame):
So, stupid ffmpeg.... Not all [en|de]coders set AVFrame->type.
This should handle the case where AVFrame->reference is set to 1 (which
is the equivalent of a keyframe).
Also fixes #323286.
I tried a truckload of other files with this modification and it didn't seem
to break playback.
This commit is contained in:
Edward Hervey 2005-12-07 12:14:34 +00:00
parent 9783a9207a
commit 3fe565fc1d
2 changed files with 31 additions and 19 deletions

View file

@ -1,3 +1,13 @@
2005-12-07 Edward Hervey <edward@fluendo.com>
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_frame):
So, stupid ffmpeg.... Not all [en|de]coders set AVFrame->type.
This should handle the case where AVFrame->reference is set to 1 (which
is the equivalent of a keyframe).
Also fixes #323286.
I tried a truckload of other files with this modification and it didn't seem
to break playback.
2005-12-06 Thomas Vander Stichele <thomas at apestaart dot org>
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),

View file

@ -804,18 +804,23 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
ffmpegdec->context->frame_number++;
switch (oclass->in_plugin->type) {
case CODEC_TYPE_VIDEO:
case CODEC_TYPE_VIDEO:
{
gboolean iskeyframe = FALSE;
ffmpegdec->picture->pict_type = -1; /* in case we skip frames */
ffmpegdec->context->opaque = ffmpegdec;
len = avcodec_decode_video (ffmpegdec->context,
ffmpegdec->picture, &have_data, data, size);
iskeyframe = ((ffmpegdec->picture->pict_type == FF_I_TYPE) || (ffmpegdec->picture->reference));
GST_DEBUG_OBJECT (ffmpegdec,
"Decoded video: len=%d, have_data=%d", len, have_data);
"Decoded video: len=%d, have_data=%d, is_keyframe:%d",
len, have_data, iskeyframe);
if (ffmpegdec->waiting_for_key) {
if (ffmpegdec->picture->pict_type == FF_I_TYPE) {
if (iskeyframe) {
ffmpegdec->waiting_for_key = FALSE;
} else {
GST_WARNING_OBJECT (ffmpegdec, "Dropping non-keyframe (seek/init)");
@ -823,21 +828,20 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
break;
}
}
/* note that ffmpeg sometimes gets the FPS wrong.
* For B-frame containing movies, we get all pictures delayed
* except for the I frames, so we synchronize only on I frames
* and keep an internal counter based on FPS for the others. */
if (!(oclass->in_plugin->capabilities & CODEC_CAP_DELAY) ||
((ffmpegdec->picture->pict_type == FF_I_TYPE ||
!GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts)) &&
GST_CLOCK_TIME_IS_VALID (*in_ts))) {
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to %" GST_TIME_FORMAT,
GST_TIME_ARGS (*in_ts));
ffmpegdec->next_ts = *in_ts;
*in_ts = GST_CLOCK_TIME_NONE;
((iskeyframe || !GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts)) &&
GST_CLOCK_TIME_IS_VALID (*in_ts))) {
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to %" GST_TIME_FORMAT,
GST_TIME_ARGS (*in_ts));
ffmpegdec->next_ts = *in_ts;
*in_ts = GST_CLOCK_TIME_NONE;
}
/* precise seeking.... */
if (GST_CLOCK_TIME_IS_VALID (ffmpegdec->synctime)) {
if (ffmpegdec->next_ts >= ffmpegdec->synctime) {
@ -859,8 +863,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
}
}
if (ffmpegdec->waiting_for_key &&
ffmpegdec->picture->pict_type != FF_I_TYPE) {
if (ffmpegdec->waiting_for_key && !iskeyframe) {
have_data = 0;
} else if (len >= 0 && have_data > 0) {
/* libavcodec constantly crashes on stupid buffer allocation
@ -904,7 +907,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
ffmpegdec->waiting_for_key = FALSE;
if (!ffmpegdec->picture->key_frame) {
if (!iskeyframe) {
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
}
@ -935,9 +938,8 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
} else if (ffmpegdec->picture->pict_type != -1 &&
oclass->in_plugin->capabilities & CODEC_CAP_DELAY) {
/* update time for skip-frame */
if ((!have_data)
|| (ffmpegdec->picture->pict_type == FF_I_TYPE ||
!GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts))
if ((!have_data) ||
(iskeyframe || !GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts))
&& GST_CLOCK_TIME_IS_VALID (*in_ts)) {
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to *in_ts");
ffmpegdec->next_ts = *in_ts;
@ -961,7 +963,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
}
}
break;
}
case CODEC_TYPE_AUDIO:
if (!ffmpegdec->last_buffer)
outbuf = gst_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);