basevideo: cater for format conversion

This commit is contained in:
Mark Nauwelaerts 2011-03-28 11:15:49 +02:00
parent 5af2f6f40e
commit 3bd16a48b4
4 changed files with 105 additions and 98 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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 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 {
res = FALSE;
}
} else {
GST_WARNING ("unhandled conversion from %d to %d", src_format,
*dest_format);
res = FALSE;
if (bytes <= 0 || time <= 0) {
GST_DEBUG ("not enough metadata yet to convert");
goto exit;
}
#endif
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;
}
exit:
return res;
}