summaryrefslogtreecommitdiff
path: root/sys/vdpau
diff options
context:
space:
mode:
authorCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2010-06-22 15:49:15 +0200
committerCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2010-06-23 21:51:53 +0200
commit90077a6f2bbd8b54c1f26de097bcb50a93567d2f (patch)
tree17b452d9e06716f6b62be41b15242d642a6e549a /sys/vdpau
parent3826b3b57b7add62a898fe6824d2386ab64778e0 (diff)
downloadgstreamer-plugins-bad-90077a6f2bbd8b54c1f26de097bcb50a93567d2f.tar.gz
vdpau: fixup decoder timestamping
Diffstat (limited to 'sys/vdpau')
-rw-r--r--sys/vdpau/basevideodecoder/gstbasevideodecoder.c121
-rw-r--r--sys/vdpau/basevideodecoder/gstbasevideodecoder.h3
-rw-r--r--sys/vdpau/h264/gstvdph264dec.c48
-rw-r--r--sys/vdpau/mpeg/gstvdpmpegdec.c4
4 files changed, 112 insertions, 64 deletions
diff --git a/sys/vdpau/basevideodecoder/gstbasevideodecoder.c b/sys/vdpau/basevideodecoder/gstbasevideodecoder.c
index 496318b70..af9590f32 100644
--- a/sys/vdpau/basevideodecoder/gstbasevideodecoder.c
+++ b/sys/vdpau/basevideodecoder/gstbasevideodecoder.c
@@ -45,6 +45,65 @@ GST_BOILERPLATE (GstBaseVideoDecoder, gst_base_video_decoder,
+typedef struct _Timestamp Timestamp;
+struct _Timestamp
+{
+ guint64 offset;
+ GstClockTime timestamp;
+ GstClockTime duration;
+};
+
+static void
+gst_base_video_decoder_add_timestamp (GstBaseVideoDecoder * base_video_decoder,
+ GstBuffer * buffer)
+{
+ Timestamp *ts;
+
+ ts = g_slice_new (Timestamp);
+
+ GST_DEBUG ("adding timestamp %" GST_TIME_FORMAT " %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (base_video_decoder->input_offset),
+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
+
+ ts->offset = base_video_decoder->input_offset;
+ ts->timestamp = GST_BUFFER_TIMESTAMP (buffer);
+ ts->duration = GST_BUFFER_DURATION (buffer);
+
+ base_video_decoder->timestamps =
+ g_list_append (base_video_decoder->timestamps, ts);
+}
+
+static void
+gst_base_video_decoder_get_timestamp_at_offset (GstBaseVideoDecoder *
+ base_video_decoder, guint64 offset, GstClockTime * timestamp,
+ GstClockTime * duration)
+{
+ GList *g;
+
+ *timestamp = GST_CLOCK_TIME_NONE;
+ *duration = GST_CLOCK_TIME_NONE;
+
+ g = base_video_decoder->timestamps;
+ while (g) {
+ Timestamp *ts;
+
+ ts = g->data;
+ if (ts->offset <= offset) {
+ *timestamp = ts->timestamp;
+ *duration = ts->duration;
+ g_slice_free (Timestamp, ts);
+ g = g_list_next (g);
+ base_video_decoder->timestamps =
+ g_list_remove (base_video_decoder->timestamps, ts);
+ } else {
+ break;
+ }
+ }
+
+ GST_DEBUG ("got timestamp %" GST_TIME_FORMAT " %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (offset), GST_TIME_ARGS (*timestamp));
+}
+
static guint64
gst_base_video_decoder_get_timestamp (GstBaseVideoDecoder * base_video_decoder,
gint picture_number)
@@ -701,39 +760,20 @@ lost_sync:
res = klass->scan_for_packet_end (dec, dec->input_adapter, &size, at_eos);
while (res == GST_BASE_VIDEO_DECODER_SCAN_RESULT_OK) {
- GstClockTime timestamp, duration;
- guint64 offset;
- gboolean preroll, gap;
-
GstBuffer *buf;
+ GstFlowReturn ret;
GST_DEBUG ("Packet size: %u", size);
if (size > gst_adapter_available (dec->input_adapter))
return GST_FLOW_OK;
- timestamp = GST_BUFFER_TIMESTAMP (dec->input_adapter->buflist->data);
- duration = GST_BUFFER_DURATION (dec->input_adapter->buflist->data);
- offset = GST_BUFFER_OFFSET (dec->input_adapter->buflist->data);
-
- preroll = GST_BUFFER_FLAG_IS_SET (dec->input_adapter->buflist->data,
- GST_BUFFER_FLAG_PREROLL);
- gap = GST_BUFFER_FLAG_IS_SET (dec->input_adapter->buflist->data,
- GST_BUFFER_FLAG_GAP);
-
buf = gst_adapter_take_buffer (dec->input_adapter, size);
- GST_BUFFER_TIMESTAMP (buf) = timestamp;
- GST_BUFFER_DURATION (buf) = duration;
- GST_BUFFER_OFFSET (buf) = offset;
+ GST_BUFFER_OFFSET (buf) = dec->input_offset -
+ gst_adapter_available (dec->input_adapter);
- if (preroll)
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_PREROLL);
- else
- GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_PREROLL);
-
- if (gap)
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP);
- else
- GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_GAP);
+ ret = klass->parse_data (dec, buf, at_eos);
+ if (ret != GST_FLOW_OK)
+ return ret;
res = klass->scan_for_packet_end (dec, dec->input_adapter, &size, at_eos);
}
@@ -810,14 +850,12 @@ gst_base_video_decoder_chain (GstPad * pad, GstBuffer * buf)
base_video_decoder->current_frame =
gst_base_video_decoder_new_frame (base_video_decoder);
}
-#if 0
- if (base_video_decoder->timestamp_offset == GST_CLOCK_TIME_NONE &&
- GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) {
- GST_DEBUG ("got new offset %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
- base_video_decoder->timestamp_offset = GST_BUFFER_TIMESTAMP (buf);
+
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+ gst_base_video_decoder_add_timestamp (base_video_decoder, buf);
}
-#endif
+ base_video_decoder->input_offset += GST_BUFFER_SIZE (buf);
+
if (base_video_decoder->packetized) {
base_video_decoder->current_frame->sink_buffer = buf;
@@ -1130,23 +1168,25 @@ gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder,
{
GstVideoFrame *frame = base_video_decoder->current_frame;
GstBaseVideoDecoderClass *klass;
+ GstClockTime timestamp, duration;
GstClockTime running_time;
GstClockTimeDiff deadline;
GstFlowReturn ret;
klass = GST_BASE_VIDEO_DECODER_GET_CLASS (base_video_decoder);
+ gst_base_video_decoder_get_timestamp_at_offset (base_video_decoder,
+ base_video_decoder->frame_offset, &timestamp, &duration);
+
+ frame->presentation_duration = timestamp;
+ frame->presentation_duration = duration;
+
if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VIDEO_FRAME_FLAG_SYNC_POINT))
base_video_decoder->distance_from_sync = 0;
frame->distance_from_sync = base_video_decoder->distance_from_sync;
base_video_decoder->distance_from_sync++;
- if (frame->sink_buffer) {
- frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (frame->sink_buffer);
- frame->presentation_duration = GST_BUFFER_DURATION (frame->sink_buffer);
- }
-
GST_DEBUG ("pts %" GST_TIME_FORMAT,
GST_TIME_ARGS (frame->presentation_timestamp));
GST_DEBUG ("dts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->decode_timestamp));
@@ -1176,6 +1216,13 @@ gst_base_video_decoder_have_frame (GstBaseVideoDecoder * base_video_decoder,
return ret;
}
+void
+gst_base_video_decoder_frame_start (GstBaseVideoDecoder * base_video_decoder,
+ GstBuffer * buf)
+{
+ base_video_decoder->frame_offset = GST_BUFFER_OFFSET (buf);
+}
+
GstVideoState *
gst_base_video_decoder_get_state (GstBaseVideoDecoder * base_video_decoder)
{
diff --git a/sys/vdpau/basevideodecoder/gstbasevideodecoder.h b/sys/vdpau/basevideodecoder/gstbasevideodecoder.h
index bdb65a9e3..556bcae80 100644
--- a/sys/vdpau/basevideodecoder/gstbasevideodecoder.h
+++ b/sys/vdpau/basevideodecoder/gstbasevideodecoder.h
@@ -184,6 +184,9 @@ GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder *base_vid
void gst_base_video_decoder_skip_frame (GstBaseVideoDecoder * base_video_decoder,
GstVideoFrame * frame);
+void
+gst_base_video_decoder_frame_start (GstBaseVideoDecoder *base_video_decoder,
+ GstBuffer *buf);
GstFlowReturn
gst_base_video_decoder_have_frame (GstBaseVideoDecoder *base_video_decoder,
GstVideoFrame **new_frame);
diff --git a/sys/vdpau/h264/gstvdph264dec.c b/sys/vdpau/h264/gstvdph264dec.c
index 0a1adb1b3..4ae79bff8 100644
--- a/sys/vdpau/h264/gstvdph264dec.c
+++ b/sys/vdpau/h264/gstvdph264dec.c
@@ -594,7 +594,6 @@ gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
return GST_FLOW_OK;
alloc_error:
- GST_ERROR_OBJECT (h264_dec, "Could not allocate output buffer");
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
return ret;
@@ -704,6 +703,7 @@ gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
gint i;
GstVideoFrame *frame;
+ GstFlowReturn ret = GST_FLOW_OK;
GST_MEMDUMP ("data", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
@@ -746,14 +746,18 @@ gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
frame = gst_base_video_decoder_get_current_frame (base_video_decoder);
/* does this mark the beginning of a new access unit */
- if (nal_unit.type == GST_NAL_AU_DELIMITER)
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ if (nal_unit.type == GST_NAL_AU_DELIMITER) {
+ ret = gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ gst_base_video_decoder_frame_start (base_video_decoder, buf);
+ }
if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY)) {
if (nal_unit.type == GST_NAL_SPS || nal_unit.type == GST_NAL_PPS ||
nal_unit.type == GST_NAL_SEI ||
- (nal_unit.type >= 14 && nal_unit.type <= 18))
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ (nal_unit.type >= 14 && nal_unit.type <= 18)) {
+ ret = gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ gst_base_video_decoder_frame_start (base_video_decoder, buf);
+ }
}
if (nal_unit.type >= GST_NAL_SLICE && nal_unit.type <= GST_NAL_SLICE_IDR) {
@@ -767,35 +771,41 @@ gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY)) {
GstH264Slice *p_slice;
guint8 pic_order_cnt_type, p_pic_order_cnt_type;
+ gboolean finish_frame = FALSE;
p_slice = &(GST_VDP_H264_FRAME_CAST (frame)->slice_hdr);
pic_order_cnt_type = slice.picture->sequence->pic_order_cnt_type;
p_pic_order_cnt_type = p_slice->picture->sequence->pic_order_cnt_type;
if (slice.frame_num != p_slice->frame_num)
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ finish_frame = TRUE;
else if (slice.picture != p_slice->picture)
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ finish_frame = TRUE;
else if (slice.bottom_field_flag != p_slice->bottom_field_flag)
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ finish_frame = TRUE;
else if (nal_unit.ref_idc != p_slice->nal_unit.ref_idc &&
(nal_unit.ref_idc == 0 || p_slice->nal_unit.ref_idc == 0))
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ finish_frame = TRUE;
else if ((pic_order_cnt_type == 0 && p_pic_order_cnt_type == 0) &&
(slice.pic_order_cnt_lsb != p_slice->pic_order_cnt_lsb ||
slice.delta_pic_order_cnt_bottom !=
p_slice->delta_pic_order_cnt_bottom))
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ finish_frame = TRUE;
else if ((p_pic_order_cnt_type == 1 && p_pic_order_cnt_type == 1) &&
(slice.delta_pic_order_cnt[0] != p_slice->delta_pic_order_cnt[0] ||
slice.delta_pic_order_cnt[1] !=
p_slice->delta_pic_order_cnt[1]))
- gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ finish_frame = TRUE;
+
+ if (finish_frame) {
+ ret = gst_base_video_decoder_have_frame (base_video_decoder, &frame);
+ gst_base_video_decoder_frame_start (base_video_decoder, buf);
+ }
}
if (!GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY)) {
@@ -820,22 +830,8 @@ gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
goto invalid_packet;
}
- if (nal_unit.type == GST_NAL_SEI) {
- GstH264Sequence *seq;
- GstH264SEIMessage sei;
-
- if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_VDP_H264_FRAME_GOT_PRIMARY))
- seq = GST_VDP_H264_FRAME_CAST (frame)->slice_hdr.picture->sequence;
- else
- seq = NULL;
-
- if (!gst_h264_parser_parse_sei_message (h264_dec->parser, seq, &sei, data,
- size))
- goto invalid_packet;
- }
-
gst_buffer_unref (buf);
- return GST_FLOW_OK;
+ return ret;
invalid_packet:
GST_WARNING ("Invalid packet size!");
diff --git a/sys/vdpau/mpeg/gstvdpmpegdec.c b/sys/vdpau/mpeg/gstvdpmpegdec.c
index f31870432..60005dfc9 100644
--- a/sys/vdpau/mpeg/gstvdpmpegdec.c
+++ b/sys/vdpau/mpeg/gstvdpmpegdec.c
@@ -477,7 +477,6 @@ gst_vdp_mpeg_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
return GST_FLOW_OK;
alloc_error:
- GST_ERROR_OBJECT (mpeg_dec, "Could not allocate output buffer");
gst_base_video_decoder_skip_frame (base_video_decoder, frame);
return ret;
@@ -546,6 +545,7 @@ gst_vdp_mpeg_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
if (mpeg_dec->prev_packet != -1) {
ret = gst_base_video_decoder_have_frame (base_video_decoder,
(GstVideoFrame **) & mpeg_frame);
+ gst_base_video_decoder_frame_start (base_video_decoder, buf);
}
mpeg_frame->seq = buf;
@@ -559,6 +559,7 @@ gst_vdp_mpeg_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
mpeg_dec->prev_packet != MPEG_PACKET_GOP) {
ret = gst_base_video_decoder_have_frame (base_video_decoder,
(GstVideoFrame **) & mpeg_frame);
+ gst_base_video_decoder_frame_start (base_video_decoder, buf);
}
mpeg_frame->pic = buf;
@@ -570,6 +571,7 @@ gst_vdp_mpeg_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
if (mpeg_dec->prev_packet != MPEG_PACKET_SEQUENCE) {
ret = gst_base_video_decoder_have_frame (base_video_decoder,
(GstVideoFrame **) & mpeg_frame);
+ gst_base_video_decoder_frame_start (base_video_decoder, buf);
}
mpeg_frame->gop = buf;