mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-25 16:48:11 +00:00
ivfparse: detect and propagate resolution changes.
Detect resolution changes on key frames, and propagate the resulting caps to the src pad. Only the uncompressed data chunk is decoded, so avoid using the new VP8 bitstream parsing library for now. Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
3b308cba3c
commit
abadffd4d8
2 changed files with 72 additions and 15 deletions
|
@ -116,8 +116,11 @@ static void
|
||||||
gst_ivf_parse_reset (GstIvfParse * ivf)
|
gst_ivf_parse_reset (GstIvfParse * ivf)
|
||||||
{
|
{
|
||||||
ivf->state = GST_IVF_PARSE_START;
|
ivf->state = GST_IVF_PARSE_START;
|
||||||
|
ivf->width = 0;
|
||||||
|
ivf->height = 0;
|
||||||
ivf->fps_n = 0;
|
ivf->fps_n = 0;
|
||||||
ivf->fps_d = 0;
|
ivf->fps_d = 0;
|
||||||
|
ivf->update_caps = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the new element
|
/* initialize the new element
|
||||||
|
@ -168,6 +171,53 @@ gst_ivf_parse_stop (GstBaseParse * parse)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_ivf_parse_set_size (GstIvfParse * ivf, guint width, guint height)
|
||||||
|
{
|
||||||
|
if (ivf->width != width || ivf->height != height) {
|
||||||
|
GST_INFO_OBJECT (ivf, "resolution changed to %ux%u", width, height);
|
||||||
|
ivf->width = width;
|
||||||
|
ivf->height = height;
|
||||||
|
ivf->update_caps = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_ivf_parse_set_framerate (GstIvfParse * ivf, guint fps_n, guint fps_d)
|
||||||
|
{
|
||||||
|
if (ivf->fps_n != fps_n || ivf->fps_d != fps_d) {
|
||||||
|
GST_INFO_OBJECT (ivf, "framerate changed to %u/%u", fps_n, fps_d);
|
||||||
|
ivf->fps_n = fps_n;
|
||||||
|
ivf->fps_d = fps_d;
|
||||||
|
ivf->update_caps = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_ivf_parse_update_src_caps (GstIvfParse * ivf)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
if (!ivf->update_caps &&
|
||||||
|
G_LIKELY (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (ivf))))
|
||||||
|
return;
|
||||||
|
ivf->update_caps = FALSE;
|
||||||
|
|
||||||
|
/* Create src pad caps */
|
||||||
|
caps = gst_caps_new_simple ("video/x-vp8", "width", G_TYPE_INT, ivf->width,
|
||||||
|
"height", G_TYPE_INT, ivf->height, NULL);
|
||||||
|
|
||||||
|
if (ivf->fps_n > 0 && ivf->fps_d > 0) {
|
||||||
|
gst_base_parse_set_frame_rate (GST_BASE_PARSE_CAST (ivf),
|
||||||
|
ivf->fps_n, ivf->fps_d, 0, 0);
|
||||||
|
gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, ivf->fps_n,
|
||||||
|
ivf->fps_d, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (ivf), caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_ivf_parse_handle_frame_start (GstIvfParse * ivf, GstBaseParseFrame * frame,
|
gst_ivf_parse_handle_frame_start (GstIvfParse * ivf, GstBaseParseFrame * frame,
|
||||||
gint * skipsize)
|
gint * skipsize)
|
||||||
|
@ -175,7 +225,6 @@ gst_ivf_parse_handle_frame_start (GstIvfParse * ivf, GstBaseParseFrame * frame,
|
||||||
GstBuffer *const buffer = frame->buffer;
|
GstBuffer *const buffer = frame->buffer;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstCaps *caps;
|
|
||||||
|
|
||||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
if (map.size >= IVF_FILE_HEADER_SIZE) {
|
if (map.size >= IVF_FILE_HEADER_SIZE) {
|
||||||
|
@ -199,23 +248,11 @@ gst_ivf_parse_handle_frame_start (GstIvfParse * ivf, GstBaseParseFrame * frame,
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ivf->fps_n = fps_n;
|
gst_ivf_parse_set_size (ivf, width, height);
|
||||||
ivf->fps_d = fps_d;
|
gst_ivf_parse_set_framerate (ivf, fps_n, fps_d);
|
||||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE_CAST (ivf),
|
|
||||||
ivf->fps_n, ivf->fps_d, 0, 0);
|
|
||||||
|
|
||||||
/* create src pad caps */
|
|
||||||
caps = gst_caps_new_simple ("video/x-vp8",
|
|
||||||
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
|
|
||||||
"framerate", GST_TYPE_FRACTION, ivf->fps_n, ivf->fps_d, NULL);
|
|
||||||
|
|
||||||
GST_INFO_OBJECT (ivf, "Found stream: %" GST_PTR_FORMAT, caps);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (ivf, "Stream has %d frames", num_frames);
|
GST_LOG_OBJECT (ivf, "Stream has %d frames", num_frames);
|
||||||
|
|
||||||
gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (ivf), caps);
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
|
|
||||||
/* move along */
|
/* move along */
|
||||||
ivf->state = GST_IVF_PARSE_DATA;
|
ivf->state = GST_IVF_PARSE_DATA;
|
||||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (ivf),
|
gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (ivf),
|
||||||
|
@ -273,12 +310,29 @@ gst_ivf_parse_handle_frame_data (GstIvfParse * ivf, GstBaseParseFrame * frame,
|
||||||
gst_buffer_replace (&frame->out_buffer, out_buffer);
|
gst_buffer_replace (&frame->out_buffer, out_buffer);
|
||||||
gst_buffer_unref (out_buffer);
|
gst_buffer_unref (out_buffer);
|
||||||
|
|
||||||
|
/* Detect resolution changes on key frames */
|
||||||
|
if (gst_buffer_map (frame->out_buffer, &map, GST_MAP_READ)) {
|
||||||
|
guint32 frame_tag, width, height;
|
||||||
|
|
||||||
|
frame_tag = GST_READ_UINT24_LE (map.data);
|
||||||
|
if (!(frame_tag & 0x01) && map.size >= 10) { /* key frame */
|
||||||
|
GST_DEBUG_OBJECT (ivf, "key frame detected");
|
||||||
|
|
||||||
|
width = GST_READ_UINT16_LE (map.data + 6) & 0x3fff;
|
||||||
|
height = GST_READ_UINT16_LE (map.data + 8) & 0x3fff;
|
||||||
|
gst_ivf_parse_set_size (ivf, width, height);
|
||||||
|
}
|
||||||
|
gst_buffer_unmap (frame->out_buffer, &map);
|
||||||
|
}
|
||||||
|
|
||||||
if (ivf->fps_n > 0) {
|
if (ivf->fps_n > 0) {
|
||||||
GST_BUFFER_TIMESTAMP (out_buffer) =
|
GST_BUFFER_TIMESTAMP (out_buffer) =
|
||||||
gst_util_uint64_scale_int (GST_SECOND * frame_pts, ivf->fps_d,
|
gst_util_uint64_scale_int (GST_SECOND * frame_pts, ivf->fps_d,
|
||||||
ivf->fps_n);
|
ivf->fps_n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_ivf_parse_update_src_caps (ivf);
|
||||||
|
|
||||||
ret = gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (ivf), frame,
|
ret = gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (ivf), frame,
|
||||||
IVF_FRAME_HEADER_SIZE + frame_size);
|
IVF_FRAME_HEADER_SIZE + frame_size);
|
||||||
*skipsize = 0;
|
*skipsize = 0;
|
||||||
|
|
|
@ -52,8 +52,11 @@ struct _GstIvfParse
|
||||||
|
|
||||||
GstIvfParseState state;
|
GstIvfParseState state;
|
||||||
|
|
||||||
|
guint width;
|
||||||
|
guint height;
|
||||||
guint fps_n;
|
guint fps_n;
|
||||||
guint fps_d;
|
guint fps_d;
|
||||||
|
gboolean update_caps;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstIvfParseClass
|
struct _GstIvfParseClass
|
||||||
|
|
Loading…
Reference in a new issue