summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2014-10-02 15:48:51 +0300
committerSebastian Dröge <sebastian@centricular.com>2014-10-03 17:23:35 +0300
commit0a31814ef3bc3b72dc27d02638af014258db1c4a (patch)
tree080896c63546b1599c58cba09507c57de5bc6e9d /ext
parent10475b67936eedce5ecdd6f960a6421899d7af09 (diff)
downloadgstreamer-plugins-bad-0a31814ef3bc3b72dc27d02638af014258db1c4a.tar.gz
openh264dec: Properly drain codec on ::finish()
Diffstat (limited to 'ext')
-rw-r--r--ext/openh264/gstopenh264dec.cpp135
1 files changed, 77 insertions, 58 deletions
diff --git a/ext/openh264/gstopenh264dec.cpp b/ext/openh264/gstopenh264dec.cpp
index 6494d4ae4..c81dba454 100644
--- a/ext/openh264/gstopenh264dec.cpp
+++ b/ext/openh264/gstopenh264dec.cpp
@@ -237,15 +237,6 @@ static gboolean gst_openh264dec_reset(GstVideoDecoder *decoder, gboolean hard)
return TRUE;
}
-static GstFlowReturn gst_openh264dec_finish(GstVideoDecoder *decoder)
-{
- GstOpenh264Dec *openh264dec = GST_OPENH264DEC(decoder);
-
- GST_DEBUG_OBJECT(openh264dec, "finish");
-
- return GST_FLOW_OK;
-}
-
static GstFlowReturn gst_openh264dec_handle_frame(GstVideoDecoder *decoder, GstVideoCodecFrame *frame)
{
GstOpenh264Dec *openh264dec = GST_OPENH264DEC(decoder);
@@ -265,67 +256,81 @@ static GstFlowReturn gst_openh264dec_handle_frame(GstVideoDecoder *decoder, GstV
guint8 *p;
guint row_stride, component_width, component_height, src_width, row;
+ if (frame) {
+ if (!gst_buffer_map(frame->input_buffer, &map_info, GST_MAP_READ)) {
+ GST_ERROR_OBJECT(openh264dec, "Cannot map input buffer!");
+ return GST_FLOW_ERROR;
+ }
- if (!gst_buffer_map(frame->input_buffer, &map_info, GST_MAP_READ)) {
- GST_ERROR_OBJECT(openh264dec, "Cannot map input buffer!");
- return GST_FLOW_ERROR;
- }
-
- GST_LOG_OBJECT(openh264dec, "handle frame, %d", map_info.size > 4 ? map_info.data[4] & 0x1f : -1);
-
- memset (&dst_buf_info, 0, sizeof (SBufferInfo));
- while (offset < map_info.size) {
+ GST_LOG_OBJECT(openh264dec, "handle frame, %d", map_info.size > 4 ? map_info.data[4] & 0x1f : -1);
- parser_result = gst_h264_parser_identify_nalu(openh264dec->priv->nal_parser,
- map_info.data, offset, map_info.size, &nalu);
- offset = nalu.offset + nalu.size;
+ while (offset < map_info.size) {
+ memset (&dst_buf_info, 0, sizeof (SBufferInfo));
+ parser_result = gst_h264_parser_identify_nalu(openh264dec->priv->nal_parser,
+ map_info.data, offset, map_info.size, &nalu);
+ offset = nalu.offset + nalu.size;
- if (parser_result != GST_H264_PARSER_OK && parser_result != GST_H264_PARSER_NO_NAL_END) {
- GST_WARNING_OBJECT(openh264dec, "Failed to identify nalu, parser result: %u", parser_result);
- break;
- }
-
- memset (&dst_buf_info, 0, sizeof (SBufferInfo));
+ if (parser_result != GST_H264_PARSER_OK && parser_result != GST_H264_PARSER_NO_NAL_END) {
+ GST_WARNING_OBJECT(openh264dec, "Failed to identify nalu, parser result: %u", parser_result);
+ break;
+ }
- ret = openh264dec->priv->decoder->DecodeFrame2(nalu.data, nalu.size + 4, yuvdata, &dst_buf_info);
+ memset (&dst_buf_info, 0, sizeof (SBufferInfo));
- if (ret == dsNoParamSets) {
- GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit");
- gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder),
- gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0));
- }
+ ret = openh264dec->priv->decoder->DecodeFrame2(nalu.data, nalu.size + 4, yuvdata, &dst_buf_info);
- if (ret != dsErrorFree && ret != dsNoParamSets) {
- GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit");
- gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder),
- gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0));
- GST_LOG_OBJECT(openh264dec, "error decoding nal, return code: %d", ret);
- GST_LOG_OBJECT(openh264dec, "nal first byte: %u", (guint) nalu.data[0]);
- GST_LOG_OBJECT(openh264dec, "nal size: %u", nalu.size);
- }
+ if (ret == dsNoParamSets) {
+ GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit");
+ gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder),
+ gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0));
+ }
- if (nalu.type == GST_H264_NAL_SPS) {
- parser_result = gst_h264_parser_parse_sps(openh264dec->priv->nal_parser, &nalu, &sps, TRUE);
- if (parser_result == GST_H264_PARSER_OK) {
- GST_DEBUG_OBJECT(openh264dec, "Got SPS, fps_n: %u fps_d: %u", sps.fps_num, sps.fps_den);
- openh264dec->priv->input_state->info.fps_n = sps.fps_num ? sps.fps_num : 30;
- openh264dec->priv->input_state->info.fps_d = sps.fps_num ? sps.fps_den : 1;
- } else {
- GST_WARNING_OBJECT(openh264dec, "Failed to parse SPS, parser result: %u", parser_result);
+ if (ret != dsErrorFree && ret != dsNoParamSets) {
+ GST_DEBUG_OBJECT(openh264dec, "Requesting a key unit");
+ gst_pad_push_event(GST_VIDEO_DECODER_SINK_PAD(decoder),
+ gst_video_event_new_upstream_force_key_unit(GST_CLOCK_TIME_NONE, FALSE, 0));
+ GST_LOG_OBJECT(openh264dec, "error decoding nal, return code: %d", ret);
+ GST_LOG_OBJECT(openh264dec, "nal first byte: %u", (guint) nalu.data[0]);
+ GST_LOG_OBJECT(openh264dec, "nal size: %u", nalu.size);
}
- } else {
- parser_result = gst_h264_parser_parse_nal(openh264dec->priv->nal_parser, &nalu);
- if (parser_result == GST_H264_PARSER_OK) {
- if (nalu.type == GST_H264_NAL_SLICE_IDR) {
- GST_DEBUG_OBJECT(openh264dec, "Got an intra picture");
- GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT(frame);
+
+ if (nalu.type == GST_H264_NAL_SPS) {
+ parser_result = gst_h264_parser_parse_sps(openh264dec->priv->nal_parser, &nalu, &sps, TRUE);
+ if (parser_result == GST_H264_PARSER_OK) {
+ GST_DEBUG_OBJECT(openh264dec, "Got SPS, fps_n: %u fps_d: %u", sps.fps_num, sps.fps_den);
+ openh264dec->priv->input_state->info.fps_n = sps.fps_num ? sps.fps_num : 30;
+ openh264dec->priv->input_state->info.fps_d = sps.fps_num ? sps.fps_den : 1;
+ } else {
+ GST_WARNING_OBJECT(openh264dec, "Failed to parse SPS, parser result: %u", parser_result);
}
} else {
- GST_WARNING_OBJECT(openh264dec, "Failed to parse nal, parser result: %u", parser_result);
+ parser_result = gst_h264_parser_parse_nal(openh264dec->priv->nal_parser, &nalu);
+ if (parser_result == GST_H264_PARSER_OK) {
+ if (nalu.type == GST_H264_NAL_SLICE_IDR) {
+ GST_DEBUG_OBJECT(openh264dec, "Got an intra picture");
+ GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT(frame);
+ }
+ } else {
+ GST_WARNING_OBJECT(openh264dec, "Failed to parse nal, parser result: %u", parser_result);
+ }
}
}
+
+ gst_buffer_unmap(frame->input_buffer, &map_info);
+ gst_video_codec_frame_unref (frame);
+ frame = NULL;
+ } else {
+ memset (&dst_buf_info, 0, sizeof (SBufferInfo));
+ ret = openh264dec->priv->decoder->DecodeFrame2(NULL, 0, yuvdata, &dst_buf_info);
+ if (ret != dsErrorFree)
+ return GST_FLOW_EOS;
+ }
+
+ frame = gst_video_decoder_get_oldest_frame (decoder);
+ if (!frame) {
+ /* Can only happen in finish() */
+ return GST_FLOW_EOS;
}
- gst_buffer_unmap(frame->input_buffer, &map_info);
if (dst_buf_info.iBufferStatus != 1) {
GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY(frame);
@@ -382,7 +387,21 @@ static GstFlowReturn gst_openh264dec_handle_frame(GstVideoDecoder *decoder, GstV
finish:
- gst_video_decoder_finish_frame(decoder, frame);
+ return gst_video_decoder_finish_frame(decoder, frame);
+}
+
+static GstFlowReturn gst_openh264dec_finish(GstVideoDecoder *decoder)
+{
+ GstOpenh264Dec *openh264dec = GST_OPENH264DEC(decoder);
+
+ GST_DEBUG_OBJECT(openh264dec, "finish");
+
+ /* Decoder not negotiated yet */
+ if (openh264dec->priv->width == 0)
+ return GST_FLOW_OK;
+
+ /* Drain all pending frames */
+ while ((gst_openh264dec_handle_frame (decoder, NULL)) == GST_FLOW_OK);
return GST_FLOW_OK;
}