mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 11:45:25 +00:00
rtpvrawpay: Implement interlacing
This commit is contained in:
parent
d8f29266e9
commit
e54ba41ff7
2 changed files with 253 additions and 210 deletions
|
@ -73,7 +73,7 @@ static GstStaticPadTemplate gst_rtp_vraw_pay_sink_template =
|
|||
"width = (int) [ 1, 32767 ], "
|
||||
"height = (int) [ 1, 32767 ]; "
|
||||
"video/x-raw-yuv, "
|
||||
"format = (fourcc) { AYUV, UYVY, I420, Y41B }, "
|
||||
"format = (fourcc) { AYUV, UYVY, I420, Y41B, UYVP }, "
|
||||
"width = (int) [ 1, 32767 ], " "height = (int) [ 1, 32767 ]; ")
|
||||
);
|
||||
|
||||
|
@ -160,6 +160,8 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
const gchar *depthstr, *samplingstr, *colorimetrystr;
|
||||
gchar *wstr, *hstr;
|
||||
gboolean interlaced;
|
||||
const gchar *color_matrix;
|
||||
gint depth;
|
||||
|
||||
rtpvrawpay = GST_RTP_VRAW_PAY (payload);
|
||||
|
||||
|
@ -170,7 +172,6 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
|
||||
/* these values are the only thing we can do */
|
||||
depthstr = "8";
|
||||
colorimetrystr = "SMPTE240M";
|
||||
|
||||
/* parse common width/height */
|
||||
res = gst_structure_get_int (s, "width", &width);
|
||||
|
@ -178,12 +179,19 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
if (!res)
|
||||
goto missing_dimension;
|
||||
|
||||
/* fail on interlaced video for now */
|
||||
if (!gst_structure_get_boolean (s, "interlaced", &interlaced))
|
||||
interlaced = FALSE;
|
||||
|
||||
if (interlaced)
|
||||
goto interlaced;
|
||||
color_matrix = gst_structure_get_string (s, "color-matrix");
|
||||
colorimetrystr = "SMPTE240M";
|
||||
if (color_matrix) {
|
||||
if (g_str_equal (color_matrix, "sdtv")) {
|
||||
/* BT.601 implies a bit more than just color-matrix */
|
||||
colorimetrystr = "BT601-5";
|
||||
} else if (g_str_equal (color_matrix, "hdtv")) {
|
||||
colorimetrystr = "BT709-2";
|
||||
}
|
||||
}
|
||||
|
||||
yp = up = vp = 0;
|
||||
xinc = yinc = 1;
|
||||
|
@ -193,6 +201,7 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
gboolean has_alpha;
|
||||
|
||||
has_alpha = gst_structure_get_int (s, "alpha_mask", &amask);
|
||||
depth = 8;
|
||||
|
||||
if (!gst_structure_get_int (s, "red_mask", &rmask))
|
||||
goto unknown_mask;
|
||||
|
@ -233,6 +242,7 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
samplingstr = "YCbCr-4:4:4";
|
||||
pgroup = 3;
|
||||
ystride = width * 4;
|
||||
depth = 8;
|
||||
break;
|
||||
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
|
||||
sampling = GST_VIDEO_FORMAT_UYVY;
|
||||
|
@ -240,6 +250,7 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
pgroup = 4;
|
||||
xinc = 2;
|
||||
ystride = GST_ROUND_UP_2 (width) * 2;
|
||||
depth = 8;
|
||||
break;
|
||||
case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
|
||||
sampling = GST_VIDEO_FORMAT_Y41B;
|
||||
|
@ -250,6 +261,7 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
uvstride = GST_ROUND_UP_8 (width) / 4;
|
||||
up = ystride * height;
|
||||
vp = up + uvstride * height;
|
||||
depth = 8;
|
||||
break;
|
||||
case GST_MAKE_FOURCC ('I', '4', '2', '0'):
|
||||
sampling = GST_VIDEO_FORMAT_I420;
|
||||
|
@ -260,6 +272,16 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
uvstride = GST_ROUND_UP_8 (width) / 2;
|
||||
up = ystride * GST_ROUND_UP_2 (height);
|
||||
vp = up + uvstride * GST_ROUND_UP_2 (height) / 2;
|
||||
depth = 8;
|
||||
break;
|
||||
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'):
|
||||
#define GST_VIDEO_FORMAT_UYVP GST_VIDEO_FORMAT_UYVY /* FIXME */
|
||||
sampling = GST_VIDEO_FORMAT_UYVP;
|
||||
samplingstr = "YCbCr-4:2:2";
|
||||
pgroup = 4;
|
||||
xinc = 2;
|
||||
ystride = GST_ROUND_UP_2 (width) * 2;
|
||||
depth = 10;
|
||||
break;
|
||||
default:
|
||||
goto unknown_fourcc;
|
||||
|
@ -267,6 +289,13 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
} else
|
||||
goto unknown_format;
|
||||
|
||||
if (interlaced) {
|
||||
yinc *= 2;
|
||||
}
|
||||
if (depth == 10) {
|
||||
depthstr = "10";
|
||||
}
|
||||
|
||||
rtpvrawpay->width = width;
|
||||
rtpvrawpay->height = height;
|
||||
rtpvrawpay->sampling = sampling;
|
||||
|
@ -278,6 +307,8 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
rtpvrawpay->vp = vp;
|
||||
rtpvrawpay->ystride = ystride;
|
||||
rtpvrawpay->uvstride = uvstride;
|
||||
rtpvrawpay->interlaced = interlaced;
|
||||
rtpvrawpay->depth = depth;
|
||||
|
||||
GST_DEBUG_OBJECT (payload, "width %d, height %d, sampling %d", width, height,
|
||||
sampling);
|
||||
|
@ -289,10 +320,17 @@ gst_rtp_vraw_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
|||
hstr = g_strdup_printf ("%d", rtpvrawpay->height);
|
||||
|
||||
gst_basertppayload_set_options (payload, "video", TRUE, "RAW", 90000);
|
||||
res = gst_basertppayload_set_outcaps (payload, "sampling", G_TYPE_STRING,
|
||||
samplingstr, "depth", G_TYPE_STRING, depthstr, "width", G_TYPE_STRING,
|
||||
wstr, "height", G_TYPE_STRING, hstr, "colorimetry", G_TYPE_STRING,
|
||||
colorimetrystr, NULL);
|
||||
if (interlaced) {
|
||||
res = gst_basertppayload_set_outcaps (payload, "sampling", G_TYPE_STRING,
|
||||
samplingstr, "depth", G_TYPE_STRING, depthstr, "width", G_TYPE_STRING,
|
||||
wstr, "height", G_TYPE_STRING, hstr, "colorimetry", G_TYPE_STRING,
|
||||
colorimetrystr, "interlace", G_TYPE_STRING, "true", NULL);
|
||||
} else {
|
||||
res = gst_basertppayload_set_outcaps (payload, "sampling", G_TYPE_STRING,
|
||||
samplingstr, "depth", G_TYPE_STRING, depthstr, "width", G_TYPE_STRING,
|
||||
wstr, "height", G_TYPE_STRING, hstr, "colorimetry", G_TYPE_STRING,
|
||||
colorimetrystr, NULL);
|
||||
}
|
||||
g_free (wstr);
|
||||
g_free (hstr);
|
||||
|
||||
|
@ -314,11 +352,6 @@ unknown_fourcc:
|
|||
GST_ERROR_OBJECT (payload, "invalid or missing fourcc");
|
||||
return FALSE;
|
||||
}
|
||||
interlaced:
|
||||
{
|
||||
GST_ERROR_OBJECT (payload, "interlaced video not supported yet");
|
||||
return FALSE;
|
||||
}
|
||||
missing_dimension:
|
||||
{
|
||||
GST_ERROR_OBJECT (payload, "missing width or height property");
|
||||
|
@ -337,6 +370,7 @@ gst_rtp_vraw_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer)
|
|||
guint size, pgroup;
|
||||
guint mtu;
|
||||
guint width, height;
|
||||
gint field;
|
||||
|
||||
rtpvrawpay = GST_RTP_VRAW_PAY (payload);
|
||||
|
||||
|
@ -361,220 +395,227 @@ gst_rtp_vraw_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer)
|
|||
height = rtpvrawpay->height;
|
||||
|
||||
/* start with line 0, offset 0 */
|
||||
line = 0;
|
||||
offset = 0;
|
||||
|
||||
/* write all lines */
|
||||
while (line < height) {
|
||||
guint left;
|
||||
GstBuffer *out;
|
||||
guint8 *outdata, *headers;
|
||||
gboolean next_line;
|
||||
guint length, cont, pixels, fieldid;
|
||||
for (field = 0; field < 1 + rtpvrawpay->interlaced; field++) {
|
||||
line = field;
|
||||
offset = 0;
|
||||
|
||||
/* get the max allowed payload length size, we try to fill the complete MTU */
|
||||
left = gst_rtp_buffer_calc_payload_len (mtu, 0, 0);
|
||||
out = gst_rtp_buffer_new_allocate (left, 0, 0);
|
||||
/* write all lines */
|
||||
while (line < height) {
|
||||
guint left;
|
||||
GstBuffer *out;
|
||||
guint8 *outdata, *headers;
|
||||
gboolean next_line;
|
||||
guint length, cont, pixels;
|
||||
|
||||
GST_BUFFER_TIMESTAMP (out) = GST_BUFFER_TIMESTAMP (buffer);
|
||||
/* get the max allowed payload length size, we try to fill the complete MTU */
|
||||
left = gst_rtp_buffer_calc_payload_len (mtu, 0, 0);
|
||||
out = gst_rtp_buffer_new_allocate (left, 0, 0);
|
||||
|
||||
outdata = gst_rtp_buffer_get_payload (out);
|
||||
|
||||
GST_LOG_OBJECT (rtpvrawpay, "created buffer of size %u for MTU %u", left,
|
||||
mtu);
|
||||
|
||||
/*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Extended Sequence Number | Length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |F| Line No |C| Offset |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Length |F| Line No |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |C| Offset | .
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ .
|
||||
* . .
|
||||
* . Two (partial) lines of video data .
|
||||
* . .
|
||||
* +---------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* need 2 bytes for the extended sequence number */
|
||||
*outdata++ = 0;
|
||||
*outdata++ = 0;
|
||||
left -= 2;
|
||||
|
||||
/* the headers start here */
|
||||
headers = outdata;
|
||||
|
||||
/* while we can fit at least one header and one pixel */
|
||||
while (left > (6 + pgroup)) {
|
||||
/* we need a 6 bytes header */
|
||||
left -= 6;
|
||||
|
||||
/* get how may bytes we need for the remaining pixels */
|
||||
pixels = width - offset;
|
||||
length = (pixels * pgroup) / rtpvrawpay->xinc;
|
||||
|
||||
if (left >= length) {
|
||||
/* pixels and header fit completely, we will write them and skip to the
|
||||
* next line. */
|
||||
next_line = TRUE;
|
||||
if (field == 0) {
|
||||
GST_BUFFER_TIMESTAMP (out) = GST_BUFFER_TIMESTAMP (buffer);
|
||||
} else {
|
||||
/* line does not fit completely, see how many pixels fit */
|
||||
pixels = (left / pgroup) * rtpvrawpay->xinc;
|
||||
GST_BUFFER_TIMESTAMP (out) = GST_BUFFER_TIMESTAMP (buffer) +
|
||||
GST_BUFFER_DURATION (buffer) / 2;
|
||||
}
|
||||
|
||||
outdata = gst_rtp_buffer_get_payload (out);
|
||||
|
||||
GST_LOG_OBJECT (rtpvrawpay, "created buffer of size %u for MTU %u", left,
|
||||
mtu);
|
||||
|
||||
/*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Extended Sequence Number | Length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |F| Line No |C| Offset |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Length |F| Line No |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |C| Offset | .
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ .
|
||||
* . .
|
||||
* . Two (partial) lines of video data .
|
||||
* . .
|
||||
* +---------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* need 2 bytes for the extended sequence number */
|
||||
*outdata++ = 0;
|
||||
*outdata++ = 0;
|
||||
left -= 2;
|
||||
|
||||
/* the headers start here */
|
||||
headers = outdata;
|
||||
|
||||
/* while we can fit at least one header and one pixel */
|
||||
while (left > (6 + pgroup)) {
|
||||
/* we need a 6 bytes header */
|
||||
left -= 6;
|
||||
|
||||
/* get how may bytes we need for the remaining pixels */
|
||||
pixels = width - offset;
|
||||
length = (pixels * pgroup) / rtpvrawpay->xinc;
|
||||
next_line = FALSE;
|
||||
}
|
||||
GST_LOG_OBJECT (rtpvrawpay, "filling %u bytes in %u pixels", length,
|
||||
pixels);
|
||||
left -= length;
|
||||
|
||||
/* write length */
|
||||
*outdata++ = (length >> 8) & 0xff;
|
||||
*outdata++ = length & 0xff;
|
||||
|
||||
/* always 0 for now */
|
||||
fieldid = 0x00;
|
||||
|
||||
/* write line no */
|
||||
*outdata++ = ((line >> 8) & 0x7f) | fieldid;
|
||||
*outdata++ = line & 0xff;
|
||||
|
||||
if (next_line) {
|
||||
/* go to next line we do this here to make the check below easier */
|
||||
line += rtpvrawpay->yinc;
|
||||
}
|
||||
|
||||
/* calculate continuation marker */
|
||||
cont = (left > (6 + pgroup) && line < height) ? 0x80 : 0x00;
|
||||
|
||||
/* write offset and continuation marker */
|
||||
*outdata++ = ((offset >> 8) & 0x7f) | cont;
|
||||
*outdata++ = offset & 0xff;
|
||||
|
||||
if (next_line) {
|
||||
/* reset offset */
|
||||
offset = 0;
|
||||
GST_LOG_OBJECT (rtpvrawpay, "go to next line %u", line);
|
||||
} else {
|
||||
offset += pixels;
|
||||
GST_LOG_OBJECT (rtpvrawpay, "next offset %u", offset);
|
||||
}
|
||||
|
||||
if (!cont)
|
||||
break;
|
||||
}
|
||||
GST_LOG_OBJECT (rtpvrawpay, "consumed %u bytes",
|
||||
(guint) (outdata - headers));
|
||||
|
||||
/* second pass, read headers and write the data */
|
||||
while (TRUE) {
|
||||
guint offs, lin;
|
||||
|
||||
/* read length and cont */
|
||||
length = (headers[0] << 8) | headers[1];
|
||||
lin = ((headers[2] & 0x7f) << 8) | headers[3];
|
||||
offs = ((headers[4] & 0x7f) << 8) | headers[5];
|
||||
cont = headers[4] & 0x80;
|
||||
pixels = length / pgroup;
|
||||
headers += 6;
|
||||
|
||||
GST_LOG_OBJECT (payload, "writing length %u, line %u, offset %u, cont %d",
|
||||
length, lin, offs, cont);
|
||||
|
||||
switch (rtpvrawpay->sampling) {
|
||||
case GST_VIDEO_FORMAT_RGB:
|
||||
case GST_VIDEO_FORMAT_RGBA:
|
||||
case GST_VIDEO_FORMAT_BGR:
|
||||
case GST_VIDEO_FORMAT_BGRA:
|
||||
case GST_VIDEO_FORMAT_UYVY:
|
||||
offs /= rtpvrawpay->xinc;
|
||||
memcpy (outdata, yp + (lin * ystride) + (offs * pgroup), length);
|
||||
outdata += length;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_AYUV:
|
||||
{
|
||||
gint i;
|
||||
guint8 *datap;
|
||||
|
||||
datap = yp + (lin * ystride) + (offs * 4);
|
||||
|
||||
for (i = 0; i < pixels; i++) {
|
||||
*outdata++ = datap[2];
|
||||
*outdata++ = datap[1];
|
||||
*outdata++ = datap[3];
|
||||
datap += 4;
|
||||
}
|
||||
break;
|
||||
if (left >= length) {
|
||||
/* pixels and header fit completely, we will write them and skip to the
|
||||
* next line. */
|
||||
next_line = TRUE;
|
||||
} else {
|
||||
/* line does not fit completely, see how many pixels fit */
|
||||
pixels = (left / pgroup) * rtpvrawpay->xinc;
|
||||
length = (pixels * pgroup) / rtpvrawpay->xinc;
|
||||
next_line = FALSE;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_I420:
|
||||
{
|
||||
gint i;
|
||||
guint uvoff;
|
||||
guint8 *yd1p, *yd2p, *udp, *vdp;
|
||||
GST_LOG_OBJECT (rtpvrawpay, "filling %u bytes in %u pixels", length,
|
||||
pixels);
|
||||
left -= length;
|
||||
|
||||
yd1p = yp + (lin * ystride) + (offs);
|
||||
yd2p = yd1p + ystride;
|
||||
uvoff =
|
||||
(lin / rtpvrawpay->yinc * uvstride) + (offs / rtpvrawpay->xinc);
|
||||
udp = up + uvoff;
|
||||
vdp = vp + uvoff;
|
||||
/* write length */
|
||||
*outdata++ = (length >> 8) & 0xff;
|
||||
*outdata++ = length & 0xff;
|
||||
|
||||
for (i = 0; i < pixels; i++) {
|
||||
*outdata++ = *yd1p++;
|
||||
*outdata++ = *yd1p++;
|
||||
*outdata++ = *yd2p++;
|
||||
*outdata++ = *yd2p++;
|
||||
*outdata++ = *udp++;
|
||||
*outdata++ = *vdp++;
|
||||
}
|
||||
break;
|
||||
/* write line no */
|
||||
*outdata++ = ((line >> 8) & 0x7f) | ((field << 7) & 0x80);
|
||||
*outdata++ = line & 0xff;
|
||||
|
||||
if (next_line) {
|
||||
/* go to next line we do this here to make the check below easier */
|
||||
line += rtpvrawpay->yinc;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_Y41B:
|
||||
{
|
||||
gint i;
|
||||
guint uvoff;
|
||||
guint8 *ydp, *udp, *vdp;
|
||||
|
||||
ydp = yp + (lin * ystride) + offs;
|
||||
uvoff =
|
||||
(lin / rtpvrawpay->yinc * uvstride) + (offs / rtpvrawpay->xinc);
|
||||
udp = up + uvoff;
|
||||
vdp = vp + uvoff;
|
||||
/* calculate continuation marker */
|
||||
cont = (left > (6 + pgroup) && line < height) ? 0x80 : 0x00;
|
||||
|
||||
for (i = 0; i < pixels; i++) {
|
||||
*outdata++ = *udp++;
|
||||
*outdata++ = *ydp++;
|
||||
*outdata++ = *ydp++;
|
||||
*outdata++ = *vdp++;
|
||||
*outdata++ = *ydp++;
|
||||
*outdata++ = *ydp++;
|
||||
}
|
||||
break;
|
||||
/* write offset and continuation marker */
|
||||
*outdata++ = ((offset >> 8) & 0x7f) | cont;
|
||||
*outdata++ = offset & 0xff;
|
||||
|
||||
if (next_line) {
|
||||
/* reset offset */
|
||||
offset = 0;
|
||||
GST_LOG_OBJECT (rtpvrawpay, "go to next line %u", line);
|
||||
} else {
|
||||
offset += pixels;
|
||||
GST_LOG_OBJECT (rtpvrawpay, "next offset %u", offset);
|
||||
}
|
||||
default:
|
||||
gst_buffer_unref (out);
|
||||
goto unknown_sampling;
|
||||
|
||||
if (!cont)
|
||||
break;
|
||||
}
|
||||
GST_LOG_OBJECT (rtpvrawpay, "consumed %u bytes",
|
||||
(guint) (outdata - headers));
|
||||
|
||||
/* second pass, read headers and write the data */
|
||||
while (TRUE) {
|
||||
guint offs, lin;
|
||||
|
||||
/* read length and cont */
|
||||
length = (headers[0] << 8) | headers[1];
|
||||
lin = ((headers[2] & 0x7f) << 8) | headers[3];
|
||||
offs = ((headers[4] & 0x7f) << 8) | headers[5];
|
||||
cont = headers[4] & 0x80;
|
||||
pixels = length / pgroup;
|
||||
headers += 6;
|
||||
|
||||
GST_LOG_OBJECT (payload,
|
||||
"writing length %u, line %u, offset %u, cont %d", length, lin, offs,
|
||||
cont);
|
||||
|
||||
switch (rtpvrawpay->sampling) {
|
||||
case GST_VIDEO_FORMAT_RGB:
|
||||
case GST_VIDEO_FORMAT_RGBA:
|
||||
case GST_VIDEO_FORMAT_BGR:
|
||||
case GST_VIDEO_FORMAT_BGRA:
|
||||
case GST_VIDEO_FORMAT_UYVY:
|
||||
offs /= rtpvrawpay->xinc;
|
||||
memcpy (outdata, yp + (lin * ystride) + (offs * pgroup), length);
|
||||
outdata += length;
|
||||
break;
|
||||
case GST_VIDEO_FORMAT_AYUV:
|
||||
{
|
||||
gint i;
|
||||
guint8 *datap;
|
||||
|
||||
datap = yp + (lin * ystride) + (offs * 4);
|
||||
|
||||
for (i = 0; i < pixels; i++) {
|
||||
*outdata++ = datap[2];
|
||||
*outdata++ = datap[1];
|
||||
*outdata++ = datap[3];
|
||||
datap += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_I420:
|
||||
{
|
||||
gint i;
|
||||
guint uvoff;
|
||||
guint8 *yd1p, *yd2p, *udp, *vdp;
|
||||
|
||||
yd1p = yp + (lin * ystride) + (offs);
|
||||
yd2p = yd1p + ystride;
|
||||
uvoff =
|
||||
(lin / rtpvrawpay->yinc * uvstride) + (offs / rtpvrawpay->xinc);
|
||||
udp = up + uvoff;
|
||||
vdp = vp + uvoff;
|
||||
|
||||
for (i = 0; i < pixels; i++) {
|
||||
*outdata++ = *yd1p++;
|
||||
*outdata++ = *yd1p++;
|
||||
*outdata++ = *yd2p++;
|
||||
*outdata++ = *yd2p++;
|
||||
*outdata++ = *udp++;
|
||||
*outdata++ = *vdp++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_VIDEO_FORMAT_Y41B:
|
||||
{
|
||||
gint i;
|
||||
guint uvoff;
|
||||
guint8 *ydp, *udp, *vdp;
|
||||
|
||||
ydp = yp + (lin * ystride) + offs;
|
||||
uvoff =
|
||||
(lin / rtpvrawpay->yinc * uvstride) + (offs / rtpvrawpay->xinc);
|
||||
udp = up + uvoff;
|
||||
vdp = vp + uvoff;
|
||||
|
||||
for (i = 0; i < pixels; i++) {
|
||||
*outdata++ = *udp++;
|
||||
*outdata++ = *ydp++;
|
||||
*outdata++ = *ydp++;
|
||||
*outdata++ = *vdp++;
|
||||
*outdata++ = *ydp++;
|
||||
*outdata++ = *ydp++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gst_buffer_unref (out);
|
||||
goto unknown_sampling;
|
||||
}
|
||||
|
||||
if (!cont)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cont)
|
||||
break;
|
||||
if (line >= height) {
|
||||
GST_LOG_OBJECT (rtpvrawpay, "field/frame complete, set marker");
|
||||
gst_rtp_buffer_set_marker (out, TRUE);
|
||||
}
|
||||
if (left > 0) {
|
||||
GST_LOG_OBJECT (rtpvrawpay, "we have %u bytes left", left);
|
||||
GST_BUFFER_SIZE (out) -= left;
|
||||
}
|
||||
|
||||
/* push buffer */
|
||||
ret = gst_basertppayload_push (payload, out);
|
||||
}
|
||||
|
||||
if (line >= height) {
|
||||
GST_LOG_OBJECT (rtpvrawpay, "frame complete, set marker");
|
||||
gst_rtp_buffer_set_marker (out, TRUE);
|
||||
}
|
||||
if (left > 0) {
|
||||
GST_LOG_OBJECT (rtpvrawpay, "we have %u bytes left", left);
|
||||
GST_BUFFER_SIZE (out) -= left;
|
||||
}
|
||||
|
||||
/* push buffer */
|
||||
ret = gst_basertppayload_push (payload, out);
|
||||
}
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ struct _GstRtpVRawPay
|
|||
guint yp, up, vp;
|
||||
gint ystride;
|
||||
gint uvstride;
|
||||
gboolean interlaced;
|
||||
gint depth;
|
||||
};
|
||||
|
||||
struct _GstRtpVRawPayClass
|
||||
|
|
Loading…
Reference in a new issue