mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
avimux: support raw BGR
https://bugzilla.gnome.org/show_bug.cgi?id=695543
This commit is contained in:
parent
d7743cf7c6
commit
065bdf5925
1 changed files with 85 additions and 12 deletions
|
@ -93,7 +93,7 @@ static GstStaticPadTemplate video_sink_factory =
|
|||
GST_PAD_SINK,
|
||||
GST_PAD_REQUEST,
|
||||
GST_STATIC_CAPS ("video/x-raw, "
|
||||
"format = (string) { YUY2, I420, GRAY8 }, "
|
||||
"format = (string) { YUY2, I420, GRAY8, BGR, BGRx, BGRA }, "
|
||||
"width = (int) [ 16, 4096 ], "
|
||||
"height = (int) [ 16, 4096 ], "
|
||||
"framerate = (fraction) [ 0, MAX ]; "
|
||||
|
@ -395,6 +395,7 @@ gst_avi_mux_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
|
|||
gint width, height;
|
||||
gint par_n, par_d;
|
||||
gboolean codec_data_in_headers = TRUE;
|
||||
gboolean valid_caps = TRUE;
|
||||
|
||||
avimux = GST_AVI_MUX (gst_pad_get_parent (pad));
|
||||
|
||||
|
@ -480,7 +481,17 @@ gst_avi_mux_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
|
|||
avipad->vids.compression = GST_MAKE_FOURCC ('Y', '8', '0', '0');
|
||||
avipad->vids.bit_cnt = 8;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_BGR:
|
||||
avipad->vids.compression = GST_MAKE_FOURCC (0x00, 0x00, 0x00, 0x00);
|
||||
avipad->vids.bit_cnt = 24;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_BGRx:
|
||||
case GST_VIDEO_FORMAT_BGRA:
|
||||
avipad->vids.compression = GST_MAKE_FOURCC (0x00, 0x00, 0x00, 0x00);
|
||||
avipad->vids.bit_cnt = 32;
|
||||
break;
|
||||
default:
|
||||
valid_caps = FALSE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -506,6 +517,8 @@ gst_avi_mux_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
|
|||
case 5:
|
||||
avipad->vids.compression = GST_MAKE_FOURCC ('D', 'X', '5', '0');
|
||||
break;
|
||||
default:
|
||||
valid_caps = FALSE;
|
||||
}
|
||||
} else if (gst_structure_has_name (structure, "video/x-msmpeg")) {
|
||||
gint msmpegversion;
|
||||
|
@ -571,6 +584,7 @@ gst_avi_mux_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
|
|||
case 3:
|
||||
avipad->vids.compression = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
|
||||
default:
|
||||
valid_caps = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -578,9 +592,11 @@ gst_avi_mux_vidsink_set_caps (GstPad * pad, GstCaps * vscaps)
|
|||
avipad->vids.compression = GST_MAKE_FOURCC ('M', 'J', '2', 'C');
|
||||
} else if (!strcmp (mimetype, "video/x-vp8")) {
|
||||
avipad->vids.compression = GST_MAKE_FOURCC ('V', 'P', '8', '0');
|
||||
} else {
|
||||
valid_caps = FALSE;
|
||||
}
|
||||
|
||||
if (!avipad->vids.compression)
|
||||
if (!valid_caps)
|
||||
goto refuse_caps;
|
||||
}
|
||||
|
||||
|
@ -1910,6 +1926,68 @@ gst_avi_mux_send_pad_data (GstAviMux * avimux, gulong num_bytes)
|
|||
return gst_pad_push (avimux->srcpad, buffer);
|
||||
}
|
||||
|
||||
#define gst_avi_mux_is_uncompressed(fourcc) \
|
||||
(fourcc == GST_RIFF_DIB || \
|
||||
fourcc == GST_RIFF_rgb || \
|
||||
fourcc == GST_RIFF_RGB || fourcc == GST_RIFF_RAW)
|
||||
|
||||
/*
|
||||
* Helper for gst_avi_demux_invert()
|
||||
*/
|
||||
static inline void
|
||||
swap_line (guint8 * d1, guint8 * d2, guint8 * tmp, gint bytes)
|
||||
{
|
||||
memcpy (tmp, d1, bytes);
|
||||
memcpy (d1, d2, bytes);
|
||||
memcpy (d2, tmp, bytes);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert DIB buffers... Takes existing buffer and
|
||||
* returns either the buffer or a new one (with old
|
||||
* one dereferenced).
|
||||
* FFMPEG does this by simply negating the height in the header. Should we?
|
||||
* FIXME: can't we preallocate tmp? and remember stride, bpp?
|
||||
* this could be done in do_one_buffer() I suppose
|
||||
*/
|
||||
static GstBuffer *
|
||||
gst_avi_mux_invert (GstAviPad * avipad, GstBuffer * buf)
|
||||
{
|
||||
gint y, w, h;
|
||||
gint bpp, stride;
|
||||
guint8 *tmp = NULL;
|
||||
GstMapInfo map;
|
||||
|
||||
GstAviVideoPad *vidpad = (GstAviVideoPad *) avipad;
|
||||
|
||||
h = vidpad->vids.height;
|
||||
w = vidpad->vids.width;
|
||||
bpp = vidpad->vids.bit_cnt ? vidpad->vids.bit_cnt : 8;
|
||||
stride = GST_ROUND_UP_4 (w * (bpp / 8));
|
||||
|
||||
buf = gst_buffer_make_writable (buf);
|
||||
|
||||
gst_buffer_map (buf, &map, GST_MAP_READWRITE);
|
||||
if (map.size < (stride * h)) {
|
||||
GST_WARNING ("Buffer is smaller than reported Width x Height x Depth");
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return buf;
|
||||
}
|
||||
|
||||
tmp = g_malloc (stride);
|
||||
|
||||
for (y = 0; y < h / 2; y++) {
|
||||
swap_line (map.data + stride * y, map.data + stride * (h - 1 - y), tmp,
|
||||
stride);
|
||||
}
|
||||
|
||||
g_free (tmp);
|
||||
|
||||
gst_buffer_unmap (buf, &map);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* do buffer */
|
||||
static GstFlowReturn
|
||||
gst_avi_mux_do_buffer (GstAviMux * avimux, GstAviPad * avipad)
|
||||
|
@ -1941,6 +2019,11 @@ gst_avi_mux_do_buffer (GstAviMux * avimux, GstAviPad * avipad)
|
|||
data = newdata;
|
||||
vidpad->prepend_buffer = NULL;
|
||||
}
|
||||
|
||||
/* DIB buffers are stored topdown (I don't know why) */
|
||||
if (gst_avi_mux_is_uncompressed (avipad->hdr.fcc_handler)) {
|
||||
data = gst_avi_mux_invert (avipad, data);
|
||||
}
|
||||
}
|
||||
|
||||
if (avimux->restart) {
|
||||
|
@ -2048,9 +2131,6 @@ gst_avi_mux_do_one_buffer (GstAviMux * avimux)
|
|||
if (!avipad->collect)
|
||||
continue;
|
||||
|
||||
if (!avipad->hdr.fcc_handler)
|
||||
goto not_negotiated;
|
||||
|
||||
buffer = gst_collect_pads_peek (avimux->collect, avipad->collect);
|
||||
if (!buffer)
|
||||
continue;
|
||||
|
@ -2093,13 +2173,6 @@ gst_avi_mux_do_one_buffer (GstAviMux * avimux)
|
|||
return GST_FLOW_EOS;
|
||||
}
|
||||
|
||||
/* ERRORS */
|
||||
not_negotiated:
|
||||
{
|
||||
GST_ELEMENT_ERROR (avimux, CORE, NEGOTIATION, (NULL),
|
||||
("pad %s not negotiated", GST_PAD_NAME (avipad->collect->pad)));
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
|
|
Loading…
Reference in a new issue