From 3bd16a48b463c66b72259e82202e315d490ccd1d Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 28 Mar 2011 11:15:49 +0200 Subject: [PATCH] basevideo: cater for format conversion --- gst-libs/gst/video/gstbasevideocodec.h | 9 ++-- gst-libs/gst/video/gstbasevideodecoder.c | 92 ++++++++------------------------ gst-libs/gst/video/gstbasevideoencoder.c | 19 +++++-- gst-libs/gst/video/gstbasevideoutils.c | 79 +++++++++++++++++++-------- 4 files changed, 103 insertions(+), 96 deletions(-) diff --git a/gst-libs/gst/video/gstbasevideocodec.h b/gst-libs/gst/video/gstbasevideocodec.h index e8f9f45..9bada93 100644 --- a/gst-libs/gst/video/gstbasevideocodec.h +++ b/gst-libs/gst/video/gstbasevideocodec.h @@ -148,6 +148,9 @@ struct _GstBaseVideoCodec GstClockTime earliest_time; gboolean discont; + gint64 bytes; + gint64 time; + /* FIXME before moving to base */ void *padding[GST_PADDING_LARGE]; }; @@ -169,9 +172,9 @@ void gst_base_video_codec_free_frame (GstVideoFrame *frame); gboolean gst_base_video_rawvideo_convert (GstVideoState *state, GstFormat src_format, gint64 src_value, GstFormat * dest_format, gint64 *dest_value); -gboolean gst_base_video_encoded_video_convert (GstVideoState *state, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 *dest_value); +gboolean gst_base_video_encoded_video_convert (GstVideoState * state, + gint64 bytes, gint64 time, GstFormat src_format, + gint64 src_value, GstFormat * dest_format, gint64 * dest_value); GstClockTime gst_video_state_get_timestamp (const GstVideoState *state, GstSegment *segment, int frame_number); diff --git a/gst-libs/gst/video/gstbasevideodecoder.c b/gst-libs/gst/video/gstbasevideodecoder.c index ac146b5..ff77098 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.c +++ b/gst-libs/gst/video/gstbasevideodecoder.c @@ -46,9 +46,6 @@ static const GstQueryType *gst_base_video_decoder_get_query_types (GstPad * pad); static gboolean gst_base_video_decoder_src_query (GstPad * pad, GstQuery * query); -static gboolean gst_base_video_decoder_src_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, GstFormat * dest_format, - gint64 * dest_value); static void gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder); @@ -324,14 +321,12 @@ gst_base_video_decoder_src_event (GstPad * pad, GstEvent * event) gst_event_unref (event); tformat = GST_FORMAT_TIME; - res = - gst_base_video_decoder_src_convert (pad, format, cur, &tformat, - &tcur); + res = gst_pad_query_convert (GST_BASE_VIDEO_CODEC_SINK_PAD + (base_video_decoder), format, cur, &tformat, &tcur); if (!res) goto convert_error; - res = - gst_base_video_decoder_src_convert (pad, format, stop, &tformat, - &tstop); + res = gst_pad_query_convert (GST_BASE_VIDEO_CODEC_SINK_PAD + (base_video_decoder), format, stop, &tformat, &tstop); if (!res) goto convert_error; @@ -400,60 +395,6 @@ convert_error: goto done; } -static gboolean -gst_base_video_decoder_src_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - GstBaseVideoDecoder *dec; - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - dec = GST_BASE_VIDEO_DECODER (gst_pad_get_parent (pad)); - - /* FIXME: check if we are in a encoding state */ - - GST_DEBUG_OBJECT (dec, "src convert"); - switch (src_format) { -#if 0 - case GST_FORMAT_DEFAULT: - switch (*dest_format) { - case GST_FORMAT_TIME: - *dest_value = gst_util_uint64_scale (granulepos_to_frame (src_value), - enc->fps_d * GST_SECOND, enc->fps_n); - break; - default: - res = FALSE; - } - break; - case GST_FORMAT_TIME: - switch (*dest_format) { - case GST_FORMAT_DEFAULT: - { - *dest_value = gst_util_uint64_scale (src_value, - enc->fps_n, enc->fps_d * GST_SECOND); - break; - } - default: - res = FALSE; - break; - } - break; -#endif - default: - res = FALSE; - break; - } - - gst_object_unref (dec); - - return res; -} - static const GstQueryType * gst_base_video_decoder_get_query_types (GstPad * pad) { @@ -513,9 +454,8 @@ gst_base_video_decoder_src_query (GstPad * pad, GstQuery * query) GST_DEBUG_OBJECT (dec, "convert query"); gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - res = - gst_base_video_decoder_src_convert (pad, src_fmt, src_val, &dest_fmt, - &dest_val); + res = gst_base_video_rawvideo_convert (&GST_BASE_VIDEO_CODEC (dec)->state, + src_fmt, src_val, &dest_fmt, &dest_val); if (!res) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); @@ -548,13 +488,13 @@ gst_base_video_decoder_sink_query (GstPad * pad, GstQuery * query) switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONVERT: { + GstBaseVideoCodec *codec = GST_BASE_VIDEO_CODEC (base_video_decoder); GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - res = - gst_base_video_rawvideo_convert (&GST_BASE_VIDEO_CODEC - (base_video_decoder)->state, src_fmt, src_val, &dest_fmt, &dest_val); + res = gst_base_video_encoded_video_convert (&codec->state, codec->bytes, + codec->time, src_fmt, src_val, &dest_fmt, &dest_val); if (!res) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); @@ -1010,6 +950,17 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, GST_BUFFER_OFFSET (src_buffer) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (src_buffer) = GST_BUFFER_OFFSET_NONE; + /* update rate estimate */ + GST_BASE_VIDEO_CODEC (base_video_decoder)->bytes += + GST_BUFFER_SIZE (src_buffer); + if (GST_CLOCK_TIME_IS_VALID (frame->presentation_duration)) { + GST_BASE_VIDEO_CODEC (base_video_decoder)->time += + frame->presentation_duration; + } else { + /* better none than nothing valid */ + GST_BASE_VIDEO_CODEC (base_video_decoder)->time = GST_CLOCK_TIME_NONE; + } + GST_DEBUG_OBJECT (base_video_decoder, "pushing frame %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->presentation_timestamp)); @@ -1294,6 +1245,9 @@ gst_base_video_decoder_set_src_caps (GstBaseVideoDecoder * base_video_decoder) caps = gst_video_format_new_caps (state->format, state->width, state->height, state->fps_n, state->fps_d, state->par_n, state->par_d); + /* arrange for derived info */ + state->bytes_per_picture = + gst_video_format_get_size (state->format, state->width, state->height); gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, state->interlaced, NULL); diff --git a/gst-libs/gst/video/gstbasevideoencoder.c b/gst-libs/gst/video/gstbasevideoencoder.c index 3514ccd..5c9950c 100644 --- a/gst-libs/gst/video/gstbasevideoencoder.c +++ b/gst-libs/gst/video/gstbasevideoencoder.c @@ -324,6 +324,8 @@ gst_base_video_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) state->interlaced = v; } + state->bytes_per_picture = + gst_video_format_get_size (state->format, state->width, state->height); state->clean_width = state->width; state->clean_height = state->height; state->clean_offset_left = 0; @@ -534,13 +536,13 @@ gst_base_video_encoder_src_query (GstPad * pad, GstQuery * query) switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CONVERT: { + GstBaseVideoCodec *codec = GST_BASE_VIDEO_CODEC (enc); GstFormat src_fmt, dest_fmt; gint64 src_val, dest_val; gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - res = - gst_base_video_encoded_video_convert (&GST_BASE_VIDEO_CODEC - (enc)->state, src_fmt, src_val, &dest_fmt, &dest_val); + res = gst_base_video_encoded_video_convert (&codec->state, + codec->bytes, codec->time, src_fmt, src_val, &dest_fmt, &dest_val); if (!res) goto error; gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); @@ -748,6 +750,17 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder, GST_BUFFER_DURATION (frame->src_buffer) = frame->presentation_duration; GST_BUFFER_OFFSET (frame->src_buffer) = frame->decode_timestamp; + /* update rate estimate */ + GST_BASE_VIDEO_CODEC (base_video_encoder)->bytes += + GST_BUFFER_SIZE (frame->src_buffer); + if (GST_CLOCK_TIME_IS_VALID (frame->presentation_duration)) { + GST_BASE_VIDEO_CODEC (base_video_encoder)->time += + frame->presentation_duration; + } else { + /* better none than nothing valid */ + GST_BASE_VIDEO_CODEC (base_video_encoder)->time = GST_CLOCK_TIME_NONE; + } + if (G_UNLIKELY (GST_BASE_VIDEO_CODEC (base_video_encoder)->discont)) { GST_LOG_OBJECT (base_video_encoder, "marking discont"); GST_BUFFER_FLAG_SET (frame->src_buffer, GST_BUFFER_FLAG_DISCONT); diff --git a/gst-libs/gst/video/gstbasevideoutils.c b/gst-libs/gst/video/gstbasevideoutils.c index 3b8b5d1..2d83213 100644 --- a/gst-libs/gst/video/gstbasevideoutils.c +++ b/gst-libs/gst/video/gstbasevideoutils.c @@ -36,7 +36,10 @@ gst_base_video_rawvideo_convert (GstVideoState * state, { gboolean res = FALSE; - if (src_format == *dest_format) { + g_return_val_if_fail (dest_format != NULL, FALSE); + g_return_val_if_fail (dest_value != NULL, FALSE); + + if (src_format == *dest_format || src_value == 0 || src_value == -1) { *dest_value = src_value; return TRUE; } @@ -66,43 +69,77 @@ gst_base_video_rawvideo_convert (GstVideoState * state, *dest_value = gst_util_uint64_scale (src_value, state->fps_n, GST_SECOND * state->fps_d); res = TRUE; + } else if (src_format == GST_FORMAT_TIME && + *dest_format == GST_FORMAT_BYTES && state->fps_d != 0 && + state->bytes_per_picture != 0) { + /* convert time to frames */ + /* FIXME subtract segment time? */ + *dest_value = gst_util_uint64_scale (src_value, + state->fps_n * state->bytes_per_picture, GST_SECOND * state->fps_d); + res = TRUE; + } else if (src_format == GST_FORMAT_BYTES && + *dest_format == GST_FORMAT_TIME && state->fps_n != 0 && + state->bytes_per_picture != 0) { + /* convert frames to time */ + /* FIXME add segment time? */ + *dest_value = gst_util_uint64_scale (src_value, + GST_SECOND * state->fps_d, state->fps_n * state->bytes_per_picture); + res = TRUE; } - /* FIXME add bytes <--> time */ - return res; } gboolean gst_base_video_encoded_video_convert (GstVideoState * state, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) + gint64 bytes, gint64 time, GstFormat src_format, + gint64 src_value, GstFormat * dest_format, gint64 * dest_value) { gboolean res = FALSE; - if (src_format == *dest_format) { - *dest_value = src_value; + g_return_val_if_fail (dest_format != NULL, FALSE); + g_return_val_if_fail (dest_value != NULL, FALSE); + + if (G_UNLIKELY (src_format == *dest_format || src_value == 0 || + src_value == -1)) { + if (dest_value) + *dest_value = src_value; return TRUE; } - GST_DEBUG ("src convert"); + if (bytes <= 0 || time <= 0) { + GST_DEBUG ("not enough metadata yet to convert"); + goto exit; + } -#if 0 - if (src_format == GST_FORMAT_DEFAULT && *dest_format == GST_FORMAT_TIME) { - if (dec->fps_d != 0) { - *dest_value = gst_util_uint64_scale (granulepos_to_frame (src_value), - dec->fps_d * GST_SECOND, dec->fps_n); - res = TRUE; - } else { + switch (src_format) { + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_TIME: + *dest_value = gst_util_uint64_scale (src_value, time, bytes); + res = TRUE; + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + *dest_value = gst_util_uint64_scale (src_value, bytes, time); + res = TRUE; + break; + default: + res = FALSE; + } + break; + default: + GST_DEBUG ("unhandled conversion from %d to %d", src_format, + *dest_format); res = FALSE; - } - } else { - GST_WARNING ("unhandled conversion from %d to %d", src_format, - *dest_format); - res = FALSE; } -#endif +exit: return res; } -- 2.7.4