summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2014-04-18 18:12:36 +0200
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2014-04-28 14:06:49 +0200
commit26ebdf259b81037dbeb1024986526d1c71d58d21 (patch)
treed52f1becbe2cab7b686a555b0899e040b249c569
parent9b1e6ca8d25f8ccfd5cd91d7ee7143fe826c6b45 (diff)
downloadgstreamer-plugins-bad-26ebdf259b81037dbeb1024986526d1c71d58d21.tar.gz
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> (cherry picked from commit abadffd4d848860ff19d4545502fc85f473a5a46)
-rw-r--r--gst/ivfparse/gstivfparse.c84
-rw-r--r--gst/ivfparse/gstivfparse.h3
2 files changed, 72 insertions, 15 deletions
diff --git a/gst/ivfparse/gstivfparse.c b/gst/ivfparse/gstivfparse.c
index d361c780c..6b5758159 100644
--- a/gst/ivfparse/gstivfparse.c
+++ b/gst/ivfparse/gstivfparse.c
@@ -116,8 +116,11 @@ static void
gst_ivf_parse_reset (GstIvfParse * ivf)
{
ivf->state = GST_IVF_PARSE_START;
+ ivf->width = 0;
+ ivf->height = 0;
ivf->fps_n = 0;
ivf->fps_d = 0;
+ ivf->update_caps = FALSE;
}
/* initialize the new element
@@ -168,6 +171,53 @@ gst_ivf_parse_stop (GstBaseParse * parse)
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
gst_ivf_parse_handle_frame_start (GstIvfParse * ivf, GstBaseParseFrame * frame,
gint * skipsize)
@@ -175,7 +225,6 @@ gst_ivf_parse_handle_frame_start (GstIvfParse * ivf, GstBaseParseFrame * frame,
GstBuffer *const buffer = frame->buffer;
GstMapInfo map;
GstFlowReturn ret = GST_FLOW_OK;
- GstCaps *caps;
gst_buffer_map (buffer, &map, GST_MAP_READ);
if (map.size >= IVF_FILE_HEADER_SIZE) {
@@ -199,23 +248,11 @@ gst_ivf_parse_handle_frame_start (GstIvfParse * ivf, GstBaseParseFrame * frame,
goto end;
}
- ivf->fps_n = fps_n;
- ivf->fps_d = 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_ivf_parse_set_size (ivf, width, height);
+ gst_ivf_parse_set_framerate (ivf, fps_n, fps_d);
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 */
ivf->state = GST_IVF_PARSE_DATA;
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_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) {
GST_BUFFER_TIMESTAMP (out_buffer) =
gst_util_uint64_scale_int (GST_SECOND * frame_pts, ivf->fps_d,
ivf->fps_n);
}
+ gst_ivf_parse_update_src_caps (ivf);
+
ret = gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (ivf), frame,
IVF_FRAME_HEADER_SIZE + frame_size);
*skipsize = 0;
diff --git a/gst/ivfparse/gstivfparse.h b/gst/ivfparse/gstivfparse.h
index c3c43f3b9..ee0c50d97 100644
--- a/gst/ivfparse/gstivfparse.h
+++ b/gst/ivfparse/gstivfparse.h
@@ -52,8 +52,11 @@ struct _GstIvfParse
GstIvfParseState state;
+ guint width;
+ guint height;
guint fps_n;
guint fps_d;
+ gboolean update_caps;
};
struct _GstIvfParseClass