mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 23:48:53 +00:00
basevideo: cater for format conversion
This commit is contained in:
parent
5af2f6f40e
commit
3bd16a48b4
4 changed files with 105 additions and 98 deletions
|
@ -148,6 +148,9 @@ struct _GstBaseVideoCodec
|
||||||
GstClockTime earliest_time;
|
GstClockTime earliest_time;
|
||||||
gboolean discont;
|
gboolean discont;
|
||||||
|
|
||||||
|
gint64 bytes;
|
||||||
|
gint64 time;
|
||||||
|
|
||||||
/* FIXME before moving to base */
|
/* FIXME before moving to base */
|
||||||
void *padding[GST_PADDING_LARGE];
|
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,
|
gboolean gst_base_video_rawvideo_convert (GstVideoState *state,
|
||||||
GstFormat src_format, gint64 src_value,
|
GstFormat src_format, gint64 src_value,
|
||||||
GstFormat * dest_format, gint64 *dest_value);
|
GstFormat * dest_format, gint64 *dest_value);
|
||||||
gboolean gst_base_video_encoded_video_convert (GstVideoState *state,
|
gboolean gst_base_video_encoded_video_convert (GstVideoState * state,
|
||||||
GstFormat src_format, gint64 src_value,
|
gint64 bytes, gint64 time, GstFormat src_format,
|
||||||
GstFormat * dest_format, gint64 *dest_value);
|
gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
|
||||||
|
|
||||||
GstClockTime gst_video_state_get_timestamp (const GstVideoState *state,
|
GstClockTime gst_video_state_get_timestamp (const GstVideoState *state,
|
||||||
GstSegment *segment, int frame_number);
|
GstSegment *segment, int frame_number);
|
||||||
|
|
|
@ -46,9 +46,6 @@ static const GstQueryType *gst_base_video_decoder_get_query_types (GstPad *
|
||||||
pad);
|
pad);
|
||||||
static gboolean gst_base_video_decoder_src_query (GstPad * pad,
|
static gboolean gst_base_video_decoder_src_query (GstPad * pad,
|
||||||
GstQuery * query);
|
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 *
|
static void gst_base_video_decoder_reset (GstBaseVideoDecoder *
|
||||||
base_video_decoder);
|
base_video_decoder);
|
||||||
|
|
||||||
|
@ -324,14 +321,12 @@ gst_base_video_decoder_src_event (GstPad * pad, GstEvent * event)
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
|
|
||||||
tformat = GST_FORMAT_TIME;
|
tformat = GST_FORMAT_TIME;
|
||||||
res =
|
res = gst_pad_query_convert (GST_BASE_VIDEO_CODEC_SINK_PAD
|
||||||
gst_base_video_decoder_src_convert (pad, format, cur, &tformat,
|
(base_video_decoder), format, cur, &tformat, &tcur);
|
||||||
&tcur);
|
|
||||||
if (!res)
|
if (!res)
|
||||||
goto convert_error;
|
goto convert_error;
|
||||||
res =
|
res = gst_pad_query_convert (GST_BASE_VIDEO_CODEC_SINK_PAD
|
||||||
gst_base_video_decoder_src_convert (pad, format, stop, &tformat,
|
(base_video_decoder), format, stop, &tformat, &tstop);
|
||||||
&tstop);
|
|
||||||
if (!res)
|
if (!res)
|
||||||
goto convert_error;
|
goto convert_error;
|
||||||
|
|
||||||
|
@ -400,60 +395,6 @@ convert_error:
|
||||||
goto done;
|
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 *
|
static const GstQueryType *
|
||||||
gst_base_video_decoder_get_query_types (GstPad * pad)
|
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_DEBUG_OBJECT (dec, "convert query");
|
||||||
|
|
||||||
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
|
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
|
||||||
res =
|
res = gst_base_video_rawvideo_convert (&GST_BASE_VIDEO_CODEC (dec)->state,
|
||||||
gst_base_video_decoder_src_convert (pad, src_fmt, src_val, &dest_fmt,
|
src_fmt, src_val, &dest_fmt, &dest_val);
|
||||||
&dest_val);
|
|
||||||
if (!res)
|
if (!res)
|
||||||
goto error;
|
goto error;
|
||||||
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
|
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)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
case GST_QUERY_CONVERT:
|
case GST_QUERY_CONVERT:
|
||||||
{
|
{
|
||||||
|
GstBaseVideoCodec *codec = GST_BASE_VIDEO_CODEC (base_video_decoder);
|
||||||
GstFormat src_fmt, dest_fmt;
|
GstFormat src_fmt, dest_fmt;
|
||||||
gint64 src_val, dest_val;
|
gint64 src_val, dest_val;
|
||||||
|
|
||||||
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
|
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
|
||||||
res =
|
res = gst_base_video_encoded_video_convert (&codec->state, codec->bytes,
|
||||||
gst_base_video_rawvideo_convert (&GST_BASE_VIDEO_CODEC
|
codec->time, src_fmt, src_val, &dest_fmt, &dest_val);
|
||||||
(base_video_decoder)->state, src_fmt, src_val, &dest_fmt, &dest_val);
|
|
||||||
if (!res)
|
if (!res)
|
||||||
goto error;
|
goto error;
|
||||||
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
|
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 (src_buffer) = GST_BUFFER_OFFSET_NONE;
|
||||||
GST_BUFFER_OFFSET_END (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_DEBUG_OBJECT (base_video_decoder, "pushing frame %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (frame->presentation_timestamp));
|
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,
|
caps = gst_video_format_new_caps (state->format,
|
||||||
state->width, state->height,
|
state->width, state->height,
|
||||||
state->fps_n, state->fps_d, state->par_n, state->par_d);
|
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",
|
gst_caps_set_simple (caps, "interlaced",
|
||||||
G_TYPE_BOOLEAN, state->interlaced, NULL);
|
G_TYPE_BOOLEAN, state->interlaced, NULL);
|
||||||
|
|
||||||
|
|
|
@ -324,6 +324,8 @@ gst_base_video_encoder_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
state->interlaced = v;
|
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_width = state->width;
|
||||||
state->clean_height = state->height;
|
state->clean_height = state->height;
|
||||||
state->clean_offset_left = 0;
|
state->clean_offset_left = 0;
|
||||||
|
@ -534,13 +536,13 @@ gst_base_video_encoder_src_query (GstPad * pad, GstQuery * query)
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
case GST_QUERY_CONVERT:
|
case GST_QUERY_CONVERT:
|
||||||
{
|
{
|
||||||
|
GstBaseVideoCodec *codec = GST_BASE_VIDEO_CODEC (enc);
|
||||||
GstFormat src_fmt, dest_fmt;
|
GstFormat src_fmt, dest_fmt;
|
||||||
gint64 src_val, dest_val;
|
gint64 src_val, dest_val;
|
||||||
|
|
||||||
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
|
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
|
||||||
res =
|
res = gst_base_video_encoded_video_convert (&codec->state,
|
||||||
gst_base_video_encoded_video_convert (&GST_BASE_VIDEO_CODEC
|
codec->bytes, codec->time, src_fmt, src_val, &dest_fmt, &dest_val);
|
||||||
(enc)->state, src_fmt, src_val, &dest_fmt, &dest_val);
|
|
||||||
if (!res)
|
if (!res)
|
||||||
goto error;
|
goto error;
|
||||||
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
|
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_DURATION (frame->src_buffer) = frame->presentation_duration;
|
||||||
GST_BUFFER_OFFSET (frame->src_buffer) = frame->decode_timestamp;
|
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)) {
|
if (G_UNLIKELY (GST_BASE_VIDEO_CODEC (base_video_encoder)->discont)) {
|
||||||
GST_LOG_OBJECT (base_video_encoder, "marking discont");
|
GST_LOG_OBJECT (base_video_encoder, "marking discont");
|
||||||
GST_BUFFER_FLAG_SET (frame->src_buffer, GST_BUFFER_FLAG_DISCONT);
|
GST_BUFFER_FLAG_SET (frame->src_buffer, GST_BUFFER_FLAG_DISCONT);
|
||||||
|
|
|
@ -36,7 +36,10 @@ gst_base_video_rawvideo_convert (GstVideoState * state,
|
||||||
{
|
{
|
||||||
gboolean res = FALSE;
|
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;
|
*dest_value = src_value;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -66,43 +69,77 @@ gst_base_video_rawvideo_convert (GstVideoState * state,
|
||||||
*dest_value = gst_util_uint64_scale (src_value, state->fps_n,
|
*dest_value = gst_util_uint64_scale (src_value, state->fps_n,
|
||||||
GST_SECOND * state->fps_d);
|
GST_SECOND * state->fps_d);
|
||||||
res = TRUE;
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_base_video_encoded_video_convert (GstVideoState * state,
|
gst_base_video_encoded_video_convert (GstVideoState * state,
|
||||||
GstFormat src_format, gint64 src_value,
|
gint64 bytes, gint64 time, GstFormat src_format,
|
||||||
GstFormat * dest_format, gint64 * dest_value)
|
gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
|
||||||
{
|
{
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
if (src_format == *dest_format) {
|
g_return_val_if_fail (dest_format != NULL, FALSE);
|
||||||
*dest_value = src_value;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("src convert");
|
if (bytes <= 0 || time <= 0) {
|
||||||
|
GST_DEBUG ("not enough metadata yet to convert");
|
||||||
#if 0
|
goto exit;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
#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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue