mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 01:30:38 +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;
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue