jpegformat: get rid of unnecessary private structs

This commit is contained in:
Tim-Philipp Müller 2018-06-23 23:51:37 +02:00
parent bfcc073ed4
commit 2fac53fa51
4 changed files with 154 additions and 188 deletions

View file

@ -95,16 +95,6 @@ typedef struct _GstJifMuxMarker
gboolean owned; gboolean owned;
} GstJifMuxMarker; } GstJifMuxMarker;
struct _GstJifMuxPrivate
{
GstPad *srcpad;
/* list of GstJifMuxMarker */
GList *markers;
guint scan_size;
const guint8 *scan_data;
};
static void gst_jif_mux_finalize (GObject * object); static void gst_jif_mux_finalize (GObject * object);
static void gst_jif_mux_reset (GstJifMux * self); static void gst_jif_mux_reset (GstJifMux * self);
@ -130,8 +120,6 @@ gst_jif_mux_class_init (GstJifMuxClass * klass)
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass; gstelement_class = (GstElementClass *) klass;
g_type_class_add_private (gobject_class, sizeof (GstJifMuxPrivate));
gobject_class->finalize = gst_jif_mux_finalize; gobject_class->finalize = gst_jif_mux_finalize;
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_jif_mux_change_state); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_jif_mux_change_state);
@ -156,9 +144,6 @@ gst_jif_mux_init (GstJifMux * self)
{ {
GstPad *sinkpad; GstPad *sinkpad;
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_JIF_MUX,
GstJifMuxPrivate);
/* create the sink and src pads */ /* create the sink and src pads */
sinkpad = gst_pad_new_from_static_template (&gst_jif_mux_sink_pad_template, sinkpad = gst_pad_new_from_static_template (&gst_jif_mux_sink_pad_template,
"sink"); "sink");
@ -167,9 +152,9 @@ gst_jif_mux_init (GstJifMux * self)
GST_DEBUG_FUNCPTR (gst_jif_mux_sink_event)); GST_DEBUG_FUNCPTR (gst_jif_mux_sink_event));
gst_element_add_pad (GST_ELEMENT (self), sinkpad); gst_element_add_pad (GST_ELEMENT (self), sinkpad);
self->priv->srcpad = self->srcpad =
gst_pad_new_from_static_template (&gst_jif_mux_src_pad_template, "src"); gst_pad_new_from_static_template (&gst_jif_mux_src_pad_template, "src");
gst_element_add_pad (GST_ELEMENT (self), self->priv->srcpad); gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
} }
static void static void
@ -193,7 +178,7 @@ gst_jif_mux_sink_setcaps (GstJifMux * self, GstCaps * caps)
/* FIXME: do we want to switch it like this or use a gobject property ? */ /* FIXME: do we want to switch it like this or use a gobject property ? */
} }
return gst_pad_set_caps (self->priv->srcpad, caps); return gst_pad_set_caps (self->srcpad, caps);
} }
static gboolean static gboolean
@ -246,12 +231,12 @@ gst_jif_mux_reset (GstJifMux * self)
GList *node; GList *node;
GstJifMuxMarker *m; GstJifMuxMarker *m;
for (node = self->priv->markers; node; node = g_list_next (node)) { for (node = self->markers; node; node = g_list_next (node)) {
m = (GstJifMuxMarker *) node->data; m = (GstJifMuxMarker *) node->data;
gst_jif_mux_marker_free (m); gst_jif_mux_marker_free (m);
} }
g_list_free (self->priv->markers); g_list_free (self->markers);
self->priv->markers = NULL; self->markers = NULL;
} }
static GstJifMuxMarker * static GstJifMuxMarker *
@ -305,12 +290,12 @@ gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf)
case SOI: case SOI:
GST_DEBUG_OBJECT (self, "marker = %x", marker); GST_DEBUG_OBJECT (self, "marker = %x", marker);
m = gst_jif_mux_new_marker (marker, 0, NULL, FALSE); m = gst_jif_mux_new_marker (marker, 0, NULL, FALSE);
self->priv->markers = g_list_prepend (self->priv->markers, m); self->markers = g_list_prepend (self->markers, m);
break; break;
case EOI: case EOI:
GST_DEBUG_OBJECT (self, "marker = %x", marker); GST_DEBUG_OBJECT (self, "marker = %x", marker);
m = gst_jif_mux_new_marker (marker, 0, NULL, FALSE); m = gst_jif_mux_new_marker (marker, 0, NULL, FALSE);
self->priv->markers = g_list_prepend (self->priv->markers, m); self->markers = g_list_prepend (self->markers, m);
goto done; goto done;
default: default:
if (!gst_byte_reader_get_uint16_be (&reader, &size)) if (!gst_byte_reader_get_uint16_be (&reader, &size))
@ -319,7 +304,7 @@ gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf)
goto error; goto error;
m = gst_jif_mux_new_marker (marker, size - 2, data, FALSE); m = gst_jif_mux_new_marker (marker, size - 2, data, FALSE);
self->priv->markers = g_list_prepend (self->priv->markers, m); self->markers = g_list_prepend (self->markers, m);
GST_DEBUG_OBJECT (self, "marker = %2x, size = %u", marker, size); GST_DEBUG_OBJECT (self, "marker = %2x, size = %u", marker, size);
break; break;
@ -343,12 +328,12 @@ gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf)
} }
/* remaining size except EOI is scan data */ /* remaining size except EOI is scan data */
self->priv->scan_size = eoi_pos - gst_byte_reader_get_pos (&reader); self->scan_size = eoi_pos - gst_byte_reader_get_pos (&reader);
if (!gst_byte_reader_get_data (&reader, self->priv->scan_size, if (!gst_byte_reader_get_data (&reader, self->scan_size,
&self->priv->scan_data)) &self->scan_data))
goto error; goto error;
GST_DEBUG_OBJECT (self, "scan data, size = %u", self->priv->scan_size); GST_DEBUG_OBJECT (self, "scan data, size = %u", self->scan_size);
} }
if (!gst_byte_reader_peek_uint8 (&reader, &marker)) if (!gst_byte_reader_peek_uint8 (&reader, &marker))
@ -358,7 +343,7 @@ gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf)
gst_byte_reader_get_pos (&reader), (guint) map.size); gst_byte_reader_get_pos (&reader), (guint) map.size);
done: done:
self->priv->markers = g_list_reverse (self->priv->markers); self->markers = g_list_reverse (self->markers);
gst_buffer_unmap (buf, &map); gst_buffer_unmap (buf, &map);
return TRUE; return TRUE;
@ -396,8 +381,8 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
*/ */
/* find some reference points where we insert before/after */ /* find some reference points where we insert before/after */
file_hdr = self->priv->markers; file_hdr = self->markers;
for (node = self->priv->markers; node; node = g_list_next (node)) { for (node = self->markers; node; node = g_list_next (node)) {
m = (GstJifMuxMarker *) node->data; m = (GstJifMuxMarker *) node->data;
switch (m->marker) { switch (m->marker) {
@ -506,8 +491,8 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
m = gst_jif_mux_new_marker (APP0, sizeof (jfif_data), m = gst_jif_mux_new_marker (APP0, sizeof (jfif_data),
(const guint8 *) &jfif_data, FALSE); (const guint8 *) &jfif_data, FALSE);
/* insert into self->markers list */ /* insert into self->markers list */
self->priv->markers = g_list_insert (self->priv->markers, m, 1); self->markers = g_list_insert (self->markers, m, 1);
app0_jfif = g_list_nth (self->priv->markers, 1); app0_jfif = g_list_nth (self->markers, 1);
} }
/* else */ /* else */
/* remove JFIF if exists */ /* remove JFIF if exists */
@ -563,12 +548,11 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
pos = app0_jfif; pos = app0_jfif;
pos = g_list_next (pos); pos = g_list_next (pos);
self->priv->markers = self->markers = g_list_insert_before (self->markers, pos, m);
g_list_insert_before (self->priv->markers, pos, m);
if (pos) { if (pos) {
app1_exif = g_list_previous (pos); app1_exif = g_list_previous (pos);
} else { } else {
app1_exif = g_list_last (self->priv->markers); app1_exif = g_list_last (self->markers);
} }
} }
modified = TRUE; modified = TRUE;
@ -607,7 +591,7 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
pos = app0_jfif; pos = app0_jfif;
pos = g_list_next (pos); pos = g_list_next (pos);
self->priv->markers = g_list_insert_before (self->priv->markers, pos, m); self->markers = g_list_insert_before (self->markers, pos, m);
} }
gst_buffer_unref (xmp_data); gst_buffer_unref (xmp_data);
@ -626,8 +610,7 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
TRUE); TRUE);
/* FIXME: if we have one already, replace */ /* FIXME: if we have one already, replace */
/* this should go before SOS, maybe at the end of file-header */ /* this should go before SOS, maybe at the end of file-header */
self->priv->markers = g_list_insert_before (self->priv->markers, self->markers = g_list_insert_before (self->markers, frame_hdr, m);
frame_hdr, m);
modified = TRUE; modified = TRUE;
} }
@ -645,12 +628,12 @@ gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
GstByteWriter *writer; GstByteWriter *writer;
GstJifMuxMarker *m; GstJifMuxMarker *m;
GList *node; GList *node;
guint size = self->priv->scan_size; guint size = self->scan_size;
gboolean writer_status = TRUE; gboolean writer_status = TRUE;
GstMapInfo map; GstMapInfo map;
/* iterate list and collect size */ /* iterate list and collect size */
for (node = self->priv->markers; node; node = g_list_next (node)) { for (node = self->markers; node; node = g_list_next (node)) {
m = (GstJifMuxMarker *) node->data; m = (GstJifMuxMarker *) node->data;
/* some markers like e.g. SOI are empty */ /* some markers like e.g. SOI are empty */
@ -674,8 +657,7 @@ gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
gst_buffer_map (buf, &map, GST_MAP_WRITE); gst_buffer_map (buf, &map, GST_MAP_WRITE);
writer = gst_byte_writer_new_with_data (map.data, map.size, TRUE); writer = gst_byte_writer_new_with_data (map.data, map.size, TRUE);
for (node = self->priv->markers; node && writer_status; for (node = self->markers; node && writer_status; node = g_list_next (node)) {
node = g_list_next (node)) {
m = (GstJifMuxMarker *) node->data; m = (GstJifMuxMarker *) node->data;
writer_status &= gst_byte_writer_put_uint8 (writer, 0xff); writer_status &= gst_byte_writer_put_uint8 (writer, 0xff);
@ -689,10 +671,9 @@ gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
} }
if (m->marker == SOS) { if (m->marker == SOS) {
GST_DEBUG_OBJECT (self, "scan data, size = %u", self->priv->scan_size); GST_DEBUG_OBJECT (self, "scan data, size = %u", self->scan_size);
writer_status &= writer_status &=
gst_byte_writer_put_data (writer, self->priv->scan_data, gst_byte_writer_put_data (writer, self->scan_data, self->scan_size);
self->priv->scan_size);
} }
} }
gst_buffer_unmap (buf, &map); gst_buffer_unmap (buf, &map);
@ -736,7 +717,7 @@ gst_jif_mux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
gst_jif_mux_reset (self); gst_jif_mux_reset (self);
if (fret == GST_FLOW_OK) { if (fret == GST_FLOW_OK) {
fret = gst_pad_push (self->priv->srcpad, buf); fret = gst_pad_push (self->srcpad, buf);
} }
return fret; return fret;
} }

View file

@ -42,12 +42,17 @@ G_BEGIN_DECLS
#define GST_JIF_MUX_CAST(obj) ((GstJifMux *) (obj)) #define GST_JIF_MUX_CAST(obj) ((GstJifMux *) (obj))
typedef struct _GstJifMux GstJifMux; typedef struct _GstJifMux GstJifMux;
typedef struct _GstJifMuxPrivate GstJifMuxPrivate;
typedef struct _GstJifMuxClass GstJifMuxClass; typedef struct _GstJifMuxClass GstJifMuxClass;
struct _GstJifMux { struct _GstJifMux {
GstElement element; GstElement element;
GstJifMuxPrivate *priv;
GstPad *srcpad;
/* list of GstJifMuxMarker */
GList *markers;
guint scan_size;
const guint8 *scan_data;
}; };
struct _GstJifMuxClass { struct _GstJifMuxClass {

View file

@ -75,40 +75,6 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_DEBUG_CATEGORY_STATIC (jpeg_parse_debug); GST_DEBUG_CATEGORY_STATIC (jpeg_parse_debug);
#define GST_CAT_DEFAULT jpeg_parse_debug #define GST_CAT_DEFAULT jpeg_parse_debug
struct _GstJpegParsePrivate
{
guint last_offset;
guint last_entropy_len;
gboolean last_resync;
/* negotiated state */
gint caps_width, caps_height;
gint caps_framerate_numerator;
gint caps_framerate_denominator;
/* the parsed frame size */
guint16 width, height;
/* format color space */
const gchar *format;
/* TRUE if the src caps sets a specific framerate */
gboolean has_fps;
/* the (expected) timestamp of the next frame */
guint64 next_ts;
/* duration of the current frame */
guint64 duration;
/* video state */
gint framerate_numerator;
gint framerate_denominator;
/* tags */
GstTagList *tags;
};
static GstFlowReturn static GstFlowReturn
gst_jpeg_parse_handle_frame (GstBaseParse * bparse, GstBaseParseFrame * frame, gst_jpeg_parse_handle_frame (GstBaseParse * bparse, GstBaseParseFrame * frame,
gint * skipsize); gint * skipsize);
@ -129,13 +95,9 @@ gst_jpeg_parse_class_init (GstJpegParseClass * klass)
{ {
GstBaseParseClass *gstbaseparse_class; GstBaseParseClass *gstbaseparse_class;
GstElementClass *gstelement_class; GstElementClass *gstelement_class;
GObjectClass *gobject_class;
gstbaseparse_class = (GstBaseParseClass *) klass; gstbaseparse_class = (GstBaseParseClass *) klass;
gstelement_class = (GstElementClass *) klass; gstelement_class = (GstElementClass *) klass;
gobject_class = (GObjectClass *) klass;
g_type_class_add_private (gobject_class, sizeof (GstJpegParsePrivate));
gstbaseparse_class->start = gst_jpeg_parse_start; gstbaseparse_class->start = gst_jpeg_parse_start;
gstbaseparse_class->stop = gst_jpeg_parse_stop; gstbaseparse_class->stop = gst_jpeg_parse_stop;
@ -161,10 +123,7 @@ gst_jpeg_parse_class_init (GstJpegParseClass * klass)
static void static void
gst_jpeg_parse_init (GstJpegParse * parse) gst_jpeg_parse_init (GstJpegParse * parse)
{ {
parse->priv = G_TYPE_INSTANCE_GET_PRIVATE (parse, GST_TYPE_JPEG_PARSE, parse->next_ts = GST_CLOCK_TIME_NONE;
GstJpegParsePrivate);
parse->priv->next_ts = GST_CLOCK_TIME_NONE;
} }
static gboolean static gboolean
@ -176,13 +135,12 @@ gst_jpeg_parse_set_sink_caps (GstBaseParse * bparse, GstCaps * caps)
if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) { if ((framerate = gst_structure_get_value (s, "framerate")) != NULL) {
if (GST_VALUE_HOLDS_FRACTION (framerate)) { if (GST_VALUE_HOLDS_FRACTION (framerate)) {
parse->priv->framerate_numerator = parse->framerate_numerator = gst_value_get_fraction_numerator (framerate);
gst_value_get_fraction_numerator (framerate); parse->framerate_denominator =
parse->priv->framerate_denominator =
gst_value_get_fraction_denominator (framerate); gst_value_get_fraction_denominator (framerate);
parse->priv->has_fps = TRUE; parse->has_fps = TRUE;
GST_DEBUG_OBJECT (parse, "got framerate of %d/%d", GST_DEBUG_OBJECT (parse, "got framerate of %d/%d",
parse->priv->framerate_numerator, parse->priv->framerate_denominator); parse->framerate_numerator, parse->framerate_denominator);
} }
} }
@ -253,15 +211,14 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse, GstMapInfo * mapinfo)
GST_DEBUG ("Parsing jpeg image data (%u bytes)", size); GST_DEBUG ("Parsing jpeg image data (%u bytes)", size);
GST_DEBUG ("Parse state: offset=%d, resync=%d, entropy len=%d", GST_DEBUG ("Parse state: offset=%d, resync=%d, entropy len=%d",
parse->priv->last_offset, parse->priv->last_resync, parse->last_offset, parse->last_resync, parse->last_entropy_len);
parse->priv->last_entropy_len);
/* offset is 2 less than actual offset; /* offset is 2 less than actual offset;
* - adapter needs at least 4 bytes for scanning, * - adapter needs at least 4 bytes for scanning,
* - start and end marker ensure at least that much * - start and end marker ensure at least that much
*/ */
/* resume from state offset */ /* resume from state offset */
offset = parse->priv->last_offset; offset = parse->last_offset;
while (1) { while (1) {
guint frame_len; guint frame_len;
@ -275,7 +232,7 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse, GstMapInfo * mapinfo)
GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2); GST_DEBUG ("Lost sync at 0x%08x, resyncing", offset + 2);
} }
/* may have marker, but could have been resyncng */ /* may have marker, but could have been resyncng */
resync = resync || parse->priv->last_resync; resync = resync || parse->last_resync;
/* Skip over extra 0xff */ /* Skip over extra 0xff */
while ((noffset >= 0) && ((value & 0xff) == 0xff)) { while ((noffset >= 0) && ((value & 0xff) == 0xff)) {
noffset++; noffset++;
@ -295,15 +252,15 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse, GstMapInfo * mapinfo)
if (value == 0xd9) { if (value == 0xd9) {
GST_DEBUG ("0x%08x: EOI marker", offset + 2); GST_DEBUG ("0x%08x: EOI marker", offset + 2);
/* clear parse state */ /* clear parse state */
parse->priv->last_resync = FALSE; parse->last_resync = FALSE;
parse->priv->last_offset = 0; parse->last_offset = 0;
return (offset + 4); return (offset + 4);
} else if (value == 0xd8) { } else if (value == 0xd8) {
/* Skip this frame if we found another SOI marker */ /* Skip this frame if we found another SOI marker */
GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2); GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
/* clear parse state */ /* clear parse state */
parse->priv->last_resync = FALSE; parse->last_resync = FALSE;
parse->priv->last_offset = 0; parse->last_offset = 0;
return -(offset + 2); return -(offset + 2);
} }
@ -326,7 +283,7 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse, GstMapInfo * mapinfo)
} }
if (gst_jpeg_parse_parse_tag_has_entropy_segment (value)) { if (gst_jpeg_parse_parse_tag_has_entropy_segment (value)) {
guint eseglen = parse->priv->last_entropy_len; guint eseglen = parse->last_entropy_len;
GST_DEBUG ("0x%08x: finding entropy segment length", offset + 2); GST_DEBUG ("0x%08x: finding entropy segment length", offset + 2);
noffset = offset + 2 + frame_len + eseglen; noffset = offset + 2 + frame_len + eseglen;
@ -335,7 +292,7 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse, GstMapInfo * mapinfo)
0x0000ff00, noffset, size - noffset, &value); 0x0000ff00, noffset, size - noffset, &value);
if (noffset < 0) { if (noffset < 0) {
/* need more data */ /* need more data */
parse->priv->last_entropy_len = size - offset - 4 - frame_len - 2; parse->last_entropy_len = size - offset - 4 - frame_len - 2;
goto need_more_data; goto need_more_data;
} }
if ((value & 0xff) != 0x00) { if ((value & 0xff) != 0x00) {
@ -344,7 +301,7 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse, GstMapInfo * mapinfo)
} }
noffset++; noffset++;
} }
parse->priv->last_entropy_len = 0; parse->last_entropy_len = 0;
frame_len += eseglen; frame_len += eseglen;
GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen, GST_DEBUG ("entropy segment length=%u => frame_len=%u", eseglen,
frame_len); frame_len);
@ -371,8 +328,8 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse, GstMapInfo * mapinfo)
/* EXITS */ /* EXITS */
need_more_data: need_more_data:
{ {
parse->priv->last_offset = offset; parse->last_offset = offset;
parse->priv->last_resync = resync; parse->last_resync = resync;
return 0; return 0;
} }
} }
@ -400,9 +357,9 @@ gst_jpeg_parse_sof (GstJpegParse * parse, GstByteReader * reader)
return FALSE; return FALSE;
/* Get w and h */ /* Get w and h */
if (!gst_byte_reader_get_uint16_be (reader, &parse->priv->height)) if (!gst_byte_reader_get_uint16_be (reader, &parse->height))
return FALSE; return FALSE;
if (!gst_byte_reader_get_uint16_be (reader, &parse->priv->width)) if (!gst_byte_reader_get_uint16_be (reader, &parse->width))
return FALSE; return FALSE;
/* Get number of components */ /* Get number of components */
@ -433,20 +390,20 @@ gst_jpeg_parse_sof (GstJpegParse * parse, GstByteReader * reader)
if (numcomps == 1) { if (numcomps == 1) {
/* gray image - no format */ /* gray image - no format */
parse->priv->format = ""; parse->format = "";
} else if (numcomps == 3) { } else if (numcomps == 3) {
temp = (blockWidth[0] * blockHeight[0]) / (blockWidth[1] * blockHeight[1]); temp = (blockWidth[0] * blockHeight[0]) / (blockWidth[1] * blockHeight[1]);
if (temp == 4 && blockHeight[0] == 2) if (temp == 4 && blockHeight[0] == 2)
parse->priv->format = "I420"; parse->format = "I420";
else if (temp == 4 && blockHeight[0] == 4) else if (temp == 4 && blockHeight[0] == 4)
parse->priv->format = "Y41B"; parse->format = "Y41B";
else if (temp == 2) else if (temp == 2)
parse->priv->format = "UYVY"; parse->format = "UYVY";
else if (temp == 1) else if (temp == 1)
parse->priv->format = "YV12"; parse->format = "YV12";
else else
parse->priv->format = ""; parse->format = "";
} else { } else {
return FALSE; return FALSE;
} }
@ -492,9 +449,9 @@ gst_jpeg_parse_skip_marker (GstJpegParse * parse,
static inline GstTagList * static inline GstTagList *
get_tag_list (GstJpegParse * parse) get_tag_list (GstJpegParse * parse)
{ {
if (!parse->priv->tags) if (!parse->tags)
parse->priv->tags = gst_tag_list_new_empty (); parse->tags = gst_tag_list_new_empty ();
return parse->priv->tags; return parse->tags;
} }
static inline void static inline void
@ -511,15 +468,14 @@ extract_and_queue_tags (GstJpegParse * parse, guint size, guint8 * data,
gst_buffer_unref (buf); gst_buffer_unref (buf);
if (tags) { if (tags) {
GstTagList *taglist = parse->priv->tags; GstTagList *taglist = parse->tags;
if (taglist) { if (taglist) {
gst_tag_list_insert (taglist, tags, GST_TAG_MERGE_REPLACE); gst_tag_list_insert (taglist, tags, GST_TAG_MERGE_REPLACE);
gst_tag_list_unref (tags); gst_tag_list_unref (tags);
} else { } else {
parse->priv->tags = tags; parse->tags = tags;
} }
GST_DEBUG_OBJECT (parse, "collected tags: %" GST_PTR_FORMAT, GST_DEBUG_OBJECT (parse, "collected tags: %" GST_PTR_FORMAT, parse->tags);
parse->priv->tags);
} }
} }
@ -719,32 +675,31 @@ gst_jpeg_parse_set_new_caps (GstJpegParse * parse, gboolean header_ok)
gboolean res; gboolean res;
GST_DEBUG_OBJECT (parse, "setting caps on srcpad (hdr_ok=%d, have_fps=%d)", GST_DEBUG_OBJECT (parse, "setting caps on srcpad (hdr_ok=%d, have_fps=%d)",
header_ok, parse->priv->has_fps); header_ok, parse->has_fps);
caps = gst_caps_new_simple ("image/jpeg", caps = gst_caps_new_simple ("image/jpeg",
"parsed", G_TYPE_BOOLEAN, TRUE, NULL); "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
if (header_ok == TRUE) { if (header_ok == TRUE) {
gst_caps_set_simple (caps, gst_caps_set_simple (caps,
"format", G_TYPE_STRING, parse->priv->format, "format", G_TYPE_STRING, parse->format,
"width", G_TYPE_INT, parse->priv->width, "width", G_TYPE_INT, parse->width,
"height", G_TYPE_INT, parse->priv->height, NULL); "height", G_TYPE_INT, parse->height, NULL);
} }
if (parse->priv->has_fps == TRUE) { if (parse->has_fps == TRUE) {
/* we have a framerate */ /* we have a framerate */
gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
parse->priv->framerate_numerator, parse->framerate_numerator, parse->framerate_denominator, NULL);
parse->priv->framerate_denominator, NULL);
if (!GST_CLOCK_TIME_IS_VALID (parse->priv->duration) if (!GST_CLOCK_TIME_IS_VALID (parse->duration)
&& parse->priv->framerate_numerator != 0) { && parse->framerate_numerator != 0) {
parse->priv->duration = gst_util_uint64_scale_int (GST_SECOND, parse->duration = gst_util_uint64_scale_int (GST_SECOND,
parse->priv->framerate_denominator, parse->priv->framerate_numerator); parse->framerate_denominator, parse->framerate_numerator);
} }
} else { } else {
/* unknown duration */ /* unknown duration */
parse->priv->duration = GST_CLOCK_TIME_NONE; parse->duration = GST_CLOCK_TIME_NONE;
gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 1, 1, NULL); gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
} }
@ -764,17 +719,17 @@ gst_jpeg_parse_pre_push_frame (GstBaseParse * bparse, GstBaseParseFrame * frame)
GstJpegParse *parse = GST_JPEG_PARSE_CAST (bparse); GstJpegParse *parse = GST_JPEG_PARSE_CAST (bparse);
GstBuffer *outbuf = frame->buffer; GstBuffer *outbuf = frame->buffer;
GST_BUFFER_TIMESTAMP (outbuf) = parse->priv->next_ts; GST_BUFFER_TIMESTAMP (outbuf) = parse->next_ts;
if (parse->priv->has_fps && GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts) if (parse->has_fps && GST_CLOCK_TIME_IS_VALID (parse->next_ts)
&& GST_CLOCK_TIME_IS_VALID (parse->priv->duration)) { && GST_CLOCK_TIME_IS_VALID (parse->duration)) {
parse->priv->next_ts += parse->priv->duration; parse->next_ts += parse->duration;
} else { } else {
parse->priv->duration = GST_CLOCK_TIME_NONE; parse->duration = GST_CLOCK_TIME_NONE;
parse->priv->next_ts = GST_CLOCK_TIME_NONE; parse->next_ts = GST_CLOCK_TIME_NONE;
} }
GST_BUFFER_DURATION (outbuf) = parse->priv->duration; GST_BUFFER_DURATION (outbuf) = parse->duration;
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -801,11 +756,11 @@ gst_jpeg_parse_handle_frame (GstBaseParse * bparse, GstBaseParseFrame * frame,
return GST_FLOW_OK; return GST_FLOW_OK;
} }
if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts))) if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (parse->next_ts)))
parse->priv->next_ts = timestamp; parse->next_ts = timestamp;
if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (duration))) if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (duration)))
parse->priv->duration = duration; parse->duration = duration;
len = gst_jpeg_parse_get_image_length (parse, &mapinfo); len = gst_jpeg_parse_get_image_length (parse, &mapinfo);
if (len == 0) { if (len == 0) {
@ -821,38 +776,35 @@ gst_jpeg_parse_handle_frame (GstBaseParse * bparse, GstBaseParseFrame * frame,
GST_LOG_OBJECT (parse, "parsed image of size %d", len); GST_LOG_OBJECT (parse, "parsed image of size %d", len);
/* reset the offset (only when we flushed) */ /* reset the offset (only when we flushed) */
parse->priv->last_offset = 0; parse->last_offset = 0;
parse->priv->last_entropy_len = 0; parse->last_entropy_len = 0;
header_ok = gst_jpeg_parse_read_header (parse, &mapinfo, len); header_ok = gst_jpeg_parse_read_header (parse, &mapinfo, len);
gst_buffer_unmap (frame->buffer, &mapinfo); gst_buffer_unmap (frame->buffer, &mapinfo);
if (parse->priv->width != parse->priv->caps_width if (parse->width != parse->caps_width
|| parse->priv->height != parse->priv->caps_height || parse->height != parse->caps_height
|| parse->priv->framerate_numerator != || parse->framerate_numerator !=
parse->priv->caps_framerate_numerator parse->caps_framerate_numerator
|| parse->priv->framerate_denominator != || parse->framerate_denominator != parse->caps_framerate_denominator) {
parse->priv->caps_framerate_denominator) {
if (!gst_jpeg_parse_set_new_caps (parse, header_ok)) { if (!gst_jpeg_parse_set_new_caps (parse, header_ok)) {
GST_ELEMENT_ERROR (parse, CORE, NEGOTIATION, GST_ELEMENT_ERROR (parse, CORE, NEGOTIATION,
("Can't set caps to the src pad"), ("Can't set caps to the src pad")); ("Can't set caps to the src pad"), ("Can't set caps to the src pad"));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
if (parse->priv->tags) { if (parse->tags) {
GST_DEBUG_OBJECT (parse, "Pushing tags: %" GST_PTR_FORMAT, GST_DEBUG_OBJECT (parse, "Pushing tags: %" GST_PTR_FORMAT, parse->tags);
parse->priv->tags);
gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse),
gst_event_new_tag (parse->priv->tags)); gst_event_new_tag (parse->tags));
parse->priv->tags = NULL; parse->tags = NULL;
} }
parse->priv->caps_width = parse->priv->width; parse->caps_width = parse->width;
parse->priv->caps_height = parse->priv->height; parse->caps_height = parse->height;
parse->priv->caps_framerate_numerator = parse->priv->framerate_numerator; parse->caps_framerate_numerator = parse->framerate_numerator;
parse->priv->caps_framerate_denominator = parse->caps_framerate_denominator = parse->framerate_denominator;
parse->priv->framerate_denominator;
} }
@ -869,11 +821,11 @@ gst_jpeg_parse_sink_event (GstBaseParse * bparse, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
parse->priv->next_ts = GST_CLOCK_TIME_NONE; parse->next_ts = GST_CLOCK_TIME_NONE;
parse->priv->duration = GST_CLOCK_TIME_NONE; parse->duration = GST_CLOCK_TIME_NONE;
parse->priv->last_offset = 0; parse->last_offset = 0;
parse->priv->last_entropy_len = 0; parse->last_entropy_len = 0;
parse->priv->last_resync = FALSE; parse->last_resync = FALSE;
res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (bparse, event); res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (bparse, event);
break; break;
case GST_EVENT_TAG:{ case GST_EVENT_TAG:{
@ -886,7 +838,7 @@ gst_jpeg_parse_sink_event (GstBaseParse * bparse, GstEvent * event)
/* Hold on to the tags till the srcpad caps are definitely set */ /* Hold on to the tags till the srcpad caps are definitely set */
gst_tag_list_insert (get_tag_list (parse), taglist, gst_tag_list_insert (get_tag_list (parse), taglist,
GST_TAG_MERGE_REPLACE); GST_TAG_MERGE_REPLACE);
GST_DEBUG ("collected tags: %" GST_PTR_FORMAT, parse->priv->tags); GST_DEBUG ("collected tags: %" GST_PTR_FORMAT, parse->tags);
gst_event_unref (event); gst_event_unref (event);
} }
break; break;
@ -906,24 +858,23 @@ gst_jpeg_parse_start (GstBaseParse * bparse)
parse = GST_JPEG_PARSE_CAST (bparse); parse = GST_JPEG_PARSE_CAST (bparse);
parse->priv->has_fps = FALSE; parse->has_fps = FALSE;
parse->priv->width = parse->priv->height = 0; parse->width = parse->height = 0;
parse->priv->framerate_numerator = 0; parse->framerate_numerator = 0;
parse->priv->framerate_denominator = 1; parse->framerate_denominator = 1;
parse->priv->caps_framerate_numerator = parse->caps_framerate_numerator = parse->caps_framerate_denominator = 0;
parse->priv->caps_framerate_denominator = 0; parse->caps_width = parse->caps_height = -1;
parse->priv->caps_width = parse->priv->caps_height = -1;
parse->priv->next_ts = GST_CLOCK_TIME_NONE; parse->next_ts = GST_CLOCK_TIME_NONE;
parse->priv->duration = GST_CLOCK_TIME_NONE; parse->duration = GST_CLOCK_TIME_NONE;
parse->priv->last_offset = 0; parse->last_offset = 0;
parse->priv->last_entropy_len = 0; parse->last_entropy_len = 0;
parse->priv->last_resync = FALSE; parse->last_resync = FALSE;
parse->priv->tags = NULL; parse->tags = NULL;
return TRUE; return TRUE;
} }
@ -935,9 +886,9 @@ gst_jpeg_parse_stop (GstBaseParse * bparse)
parse = GST_JPEG_PARSE_CAST (bparse); parse = GST_JPEG_PARSE_CAST (bparse);
if (parse->priv->tags) { if (parse->tags) {
gst_tag_list_unref (parse->priv->tags); gst_tag_list_unref (parse->tags);
parse->priv->tags = NULL; parse->tags = NULL;
} }
return TRUE; return TRUE;

View file

@ -44,12 +44,41 @@ G_BEGIN_DECLS
#define GST_JPEG_PARSE_CAST(obj) ((GstJpegParse *)obj) #define GST_JPEG_PARSE_CAST(obj) ((GstJpegParse *)obj)
typedef struct _GstJpegParse GstJpegParse; typedef struct _GstJpegParse GstJpegParse;
typedef struct _GstJpegParsePrivate GstJpegParsePrivate;
typedef struct _GstJpegParseClass GstJpegParseClass; typedef struct _GstJpegParseClass GstJpegParseClass;
struct _GstJpegParse { struct _GstJpegParse {
GstBaseParse parse; GstBaseParse parse;
GstJpegParsePrivate *priv;
guint last_offset;
guint last_entropy_len;
gboolean last_resync;
/* negotiated state */
gint caps_width, caps_height;
gint caps_framerate_numerator;
gint caps_framerate_denominator;
/* the parsed frame size */
guint16 width, height;
/* format color space */
const gchar *format;
/* TRUE if the src caps sets a specific framerate */
gboolean has_fps;
/* the (expected) timestamp of the next frame */
guint64 next_ts;
/* duration of the current frame */
guint64 duration;
/* video state */
gint framerate_numerator;
gint framerate_denominator;
/* tags */
GstTagList *tags;
}; };
struct _GstJpegParseClass { struct _GstJpegParseClass {