mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 14:56:36 +00:00
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:
parent
9783a9207a
commit
3fe565fc1d
2 changed files with 31 additions and 19 deletions
10
ChangeLog
10
ChangeLog
|
@ -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>
|
2005-12-06 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),
|
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),
|
||||||
|
|
|
@ -804,18 +804,23 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
ffmpegdec->context->frame_number++;
|
ffmpegdec->context->frame_number++;
|
||||||
|
|
||||||
switch (oclass->in_plugin->type) {
|
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->picture->pict_type = -1; /* in case we skip frames */
|
||||||
|
|
||||||
ffmpegdec->context->opaque = ffmpegdec;
|
ffmpegdec->context->opaque = ffmpegdec;
|
||||||
|
|
||||||
len = avcodec_decode_video (ffmpegdec->context,
|
len = avcodec_decode_video (ffmpegdec->context,
|
||||||
ffmpegdec->picture, &have_data, data, size);
|
ffmpegdec->picture, &have_data, data, size);
|
||||||
|
iskeyframe = ((ffmpegdec->picture->pict_type == FF_I_TYPE) || (ffmpegdec->picture->reference));
|
||||||
GST_DEBUG_OBJECT (ffmpegdec,
|
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->waiting_for_key) {
|
||||||
if (ffmpegdec->picture->pict_type == FF_I_TYPE) {
|
if (iskeyframe) {
|
||||||
ffmpegdec->waiting_for_key = FALSE;
|
ffmpegdec->waiting_for_key = FALSE;
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING_OBJECT (ffmpegdec, "Dropping non-keyframe (seek/init)");
|
GST_WARNING_OBJECT (ffmpegdec, "Dropping non-keyframe (seek/init)");
|
||||||
|
@ -823,21 +828,20 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* note that ffmpeg sometimes gets the FPS wrong.
|
/* note that ffmpeg sometimes gets the FPS wrong.
|
||||||
* For B-frame containing movies, we get all pictures delayed
|
* For B-frame containing movies, we get all pictures delayed
|
||||||
* except for the I frames, so we synchronize only on I frames
|
* except for the I frames, so we synchronize only on I frames
|
||||||
* and keep an internal counter based on FPS for the others. */
|
* and keep an internal counter based on FPS for the others. */
|
||||||
if (!(oclass->in_plugin->capabilities & CODEC_CAP_DELAY) ||
|
if (!(oclass->in_plugin->capabilities & CODEC_CAP_DELAY) ||
|
||||||
((ffmpegdec->picture->pict_type == FF_I_TYPE ||
|
((iskeyframe || !GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts)) &&
|
||||||
!GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts)) &&
|
GST_CLOCK_TIME_IS_VALID (*in_ts))) {
|
||||||
GST_CLOCK_TIME_IS_VALID (*in_ts))) {
|
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to %" GST_TIME_FORMAT,
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to %" GST_TIME_FORMAT,
|
GST_TIME_ARGS (*in_ts));
|
||||||
GST_TIME_ARGS (*in_ts));
|
ffmpegdec->next_ts = *in_ts;
|
||||||
ffmpegdec->next_ts = *in_ts;
|
*in_ts = GST_CLOCK_TIME_NONE;
|
||||||
*in_ts = GST_CLOCK_TIME_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* precise seeking.... */
|
/* precise seeking.... */
|
||||||
if (GST_CLOCK_TIME_IS_VALID (ffmpegdec->synctime)) {
|
if (GST_CLOCK_TIME_IS_VALID (ffmpegdec->synctime)) {
|
||||||
if (ffmpegdec->next_ts >= ffmpegdec->synctime) {
|
if (ffmpegdec->next_ts >= ffmpegdec->synctime) {
|
||||||
|
@ -859,8 +863,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ffmpegdec->waiting_for_key &&
|
if (ffmpegdec->waiting_for_key && !iskeyframe) {
|
||||||
ffmpegdec->picture->pict_type != FF_I_TYPE) {
|
|
||||||
have_data = 0;
|
have_data = 0;
|
||||||
} else if (len >= 0 && have_data > 0) {
|
} else if (len >= 0 && have_data > 0) {
|
||||||
/* libavcodec constantly crashes on stupid buffer allocation
|
/* libavcodec constantly crashes on stupid buffer allocation
|
||||||
|
@ -904,7 +907,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
|
|
||||||
ffmpegdec->waiting_for_key = FALSE;
|
ffmpegdec->waiting_for_key = FALSE;
|
||||||
|
|
||||||
if (!ffmpegdec->picture->key_frame) {
|
if (!iskeyframe) {
|
||||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
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 &&
|
} else if (ffmpegdec->picture->pict_type != -1 &&
|
||||||
oclass->in_plugin->capabilities & CODEC_CAP_DELAY) {
|
oclass->in_plugin->capabilities & CODEC_CAP_DELAY) {
|
||||||
/* update time for skip-frame */
|
/* update time for skip-frame */
|
||||||
if ((!have_data)
|
if ((!have_data) ||
|
||||||
|| (ffmpegdec->picture->pict_type == FF_I_TYPE ||
|
(iskeyframe || !GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts))
|
||||||
!GST_CLOCK_TIME_IS_VALID (ffmpegdec->next_ts))
|
|
||||||
&& GST_CLOCK_TIME_IS_VALID (*in_ts)) {
|
&& GST_CLOCK_TIME_IS_VALID (*in_ts)) {
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to *in_ts");
|
GST_DEBUG_OBJECT (ffmpegdec, "setting next_ts to *in_ts");
|
||||||
ffmpegdec->next_ts = *in_ts;
|
ffmpegdec->next_ts = *in_ts;
|
||||||
|
@ -961,7 +963,7 @@ gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CODEC_TYPE_AUDIO:
|
case CODEC_TYPE_AUDIO:
|
||||||
if (!ffmpegdec->last_buffer)
|
if (!ffmpegdec->last_buffer)
|
||||||
outbuf = gst_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
outbuf = gst_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
||||||
|
|
Loading…
Reference in a new issue