mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
codecparser: mpeg4: Look for resync code in _mpeg4_parse
This way the API is simpler and users can call 1 single function for packet detection.
This commit is contained in:
parent
5555b5fa9d
commit
e1bacb4813
3 changed files with 117 additions and 77 deletions
|
@ -286,14 +286,14 @@ failed:
|
|||
}
|
||||
|
||||
static inline guint8
|
||||
compute_resync_marker_size (const GstMpeg4VideoObjectPlane * vop)
|
||||
compute_resync_marker_size (const GstMpeg4VideoObjectPlane * vop,
|
||||
guint32 * pattern, guint32 * mask)
|
||||
{
|
||||
guint8 off;
|
||||
/* FIXME handle the binary only shape case */
|
||||
switch (vop->coding_type) {
|
||||
case (GST_MPEG4_I_VOP):
|
||||
off = 16;
|
||||
|
||||
break;
|
||||
case (GST_MPEG4_S_VOP):
|
||||
case (GST_MPEG4_P_VOP):
|
||||
|
@ -308,15 +308,105 @@ compute_resync_marker_size (const GstMpeg4VideoObjectPlane * vop)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (mask && pattern) {
|
||||
switch (off) {
|
||||
case 16:
|
||||
*pattern = 0x00008;
|
||||
*mask = 0xfffff;
|
||||
break;
|
||||
case 17:
|
||||
*pattern = 0x00004;
|
||||
*mask = 0xfffff;
|
||||
break;
|
||||
case 18:
|
||||
*pattern = 0x00002;
|
||||
*mask = 0xfffff;
|
||||
break;
|
||||
case 19:
|
||||
*pattern = 0x00001;
|
||||
*mask = 0xfffff;
|
||||
break;
|
||||
case 20:
|
||||
*pattern = 0x000008;
|
||||
*mask = 0xffffff;
|
||||
break;
|
||||
case 21:
|
||||
*pattern = 0x000004;
|
||||
*mask = 0xffffff;
|
||||
break;
|
||||
case 22:
|
||||
*pattern = 0x000002;
|
||||
*mask = 0xffffff;
|
||||
break;
|
||||
case 23:
|
||||
*pattern = 0x000001;
|
||||
*mask = 0xffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return off++; /* Take the following 1 into account */
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mpeg4_next_resync:
|
||||
* @packet: The #GstMpeg4Packet to fill
|
||||
* @vop: The previously parsed #GstMpeg4VideoObjectPlane
|
||||
* @offset: offset from which to start the parsing
|
||||
* @data: The data to parse
|
||||
* @size: The size of the @data to parse
|
||||
*
|
||||
* Parses @data and fills @packet with the information of the next resync packet
|
||||
* found.
|
||||
*
|
||||
* Returns: a #GstMpeg4ParseResult
|
||||
*/
|
||||
static GstMpeg4ParseResult
|
||||
gst_mpeg4_next_resync (GstMpeg4Packet * packet,
|
||||
const GstMpeg4VideoObjectPlane * vop, const guint8 * data, gsize size)
|
||||
{
|
||||
guint markersize = 0, off1, off2;
|
||||
guint32 mask = 0xff, pattern = 0xff;
|
||||
GstByteReader br;
|
||||
|
||||
gst_byte_reader_init (&br, data, size);
|
||||
|
||||
g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR);
|
||||
g_return_val_if_fail (vop != NULL, GST_MPEG4_PARSER_ERROR);
|
||||
|
||||
markersize = compute_resync_marker_size (vop, &pattern, &mask);
|
||||
|
||||
off1 = gst_byte_reader_masked_scan_uint32 (&br, mask, pattern, 0, size);
|
||||
|
||||
if (off1 < 0)
|
||||
return GST_MPEG4_PARSER_NO_PACKET;
|
||||
|
||||
GST_DEBUG ("Resync code found at %i", off1);
|
||||
|
||||
packet->offset = off1;
|
||||
packet->type = GST_MPEG4_RESYNC;
|
||||
packet->marker_size = markersize;
|
||||
|
||||
off2 = gst_byte_reader_masked_scan_uint32 (&br, mask, pattern,
|
||||
off1, size - off1);
|
||||
|
||||
if (off2 < 0)
|
||||
return GST_MPEG4_PARSER_NO_PACKET_END;
|
||||
|
||||
packet->size = off1 - off2;
|
||||
|
||||
return GST_MPEG4_PARSER_OK;
|
||||
}
|
||||
|
||||
|
||||
/********** API **********/
|
||||
|
||||
/**
|
||||
* gst_mpeg4_parse:
|
||||
* @packet: The #GstMpeg4Packet to fill
|
||||
* @skip_user_data: %TRUE to skip user data packet %FALSE otherwize
|
||||
* @vop: The last parsed #GstMpeg4VideoObjectPlane or %NULL if you do
|
||||
* not need to detect the resync codes.
|
||||
* @offset: offset from which to start the parsing
|
||||
* @data: The data to parse
|
||||
* @size: The size of the @data to parse
|
||||
|
@ -328,10 +418,12 @@ compute_resync_marker_size (const GstMpeg4VideoObjectPlane * vop)
|
|||
*/
|
||||
GstMpeg4ParseResult
|
||||
gst_mpeg4_parse (GstMpeg4Packet * packet, gboolean skip_user_data,
|
||||
const guint8 * data, guint offset, gsize size)
|
||||
GstMpeg4VideoObjectPlane * vop, const guint8 * data, guint offset,
|
||||
gsize size)
|
||||
{
|
||||
gint off1, off2;
|
||||
GstByteReader br;
|
||||
GstMpeg4ParseResult resync_res;
|
||||
|
||||
gst_byte_reader_init (&br, data, size);
|
||||
|
||||
|
@ -345,6 +437,18 @@ gst_mpeg4_parse (GstMpeg4Packet * packet, gboolean skip_user_data,
|
|||
return GST_MPEG4_PARSER_ERROR;
|
||||
}
|
||||
|
||||
if (vop) {
|
||||
resync_res =
|
||||
gst_mpeg4_next_resync (packet, vop, data + offset, size - offset);
|
||||
|
||||
/* We found a complet slice */
|
||||
if (resync_res == GST_MPEG4_PARSER_OK)
|
||||
return resync_res;
|
||||
|
||||
else if (resync_res == GST_MPEG4_PARSER_OK)
|
||||
goto find_end;
|
||||
}
|
||||
|
||||
off1 = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100,
|
||||
offset, size - offset);
|
||||
|
||||
|
@ -355,13 +459,16 @@ gst_mpeg4_parse (GstMpeg4Packet * packet, gboolean skip_user_data,
|
|||
|
||||
/* Recursively skip user data if needed */
|
||||
if (skip_user_data && data[off1 + 3] == GST_MPEG4_USER_DATA)
|
||||
return gst_mpeg4_parse (packet, skip_user_data, data, off1 + 3,
|
||||
/* If we are here, we know no resync code has been found the first time, so we
|
||||
* don't look for it this time */
|
||||
return gst_mpeg4_parse (packet, skip_user_data, NULL, data, off1 + 3,
|
||||
size - off1 - 3);
|
||||
|
||||
packet->offset = off1 + 3;
|
||||
packet->data = data;
|
||||
packet->type = (GstMpeg4StartCode) (data[off1 + 3]);
|
||||
|
||||
find_end:
|
||||
off2 = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100,
|
||||
off1 + 4, size - off1 - 4);
|
||||
|
||||
|
@ -1464,68 +1571,6 @@ failed:
|
|||
return GST_MPEG4_PARSER_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mpeg4_next_resync:
|
||||
* @packet: The #GstMpeg4Packet to fill
|
||||
* @vop: The previously parsed #GstMpeg4VideoObjectPlane
|
||||
* @offset: offset from which to start the parsing
|
||||
* @data: The data to parse
|
||||
* @size: The size of the @data to parse
|
||||
*
|
||||
* Parses @data and fills @packet with the information of the next resync packet
|
||||
* found.
|
||||
*
|
||||
* Returns: a #GstMpeg4ParseResult
|
||||
*/
|
||||
GstMpeg4ParseResult
|
||||
gst_mpeg4_next_resync (GstMpeg4Packet * packet,
|
||||
const GstMpeg4VideoObjectPlane * vop, const guint8 * data, gsize size)
|
||||
{
|
||||
guint markersize = 0, skip, remaining;
|
||||
GstBitReader br;
|
||||
|
||||
gst_bit_reader_init (&br, data, size);
|
||||
|
||||
g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR);
|
||||
g_return_val_if_fail (vop != NULL, GST_MPEG4_PARSER_ERROR);
|
||||
|
||||
/* Skip to the end of the vop header */
|
||||
gst_bit_reader_skip (&br, vop->size);
|
||||
|
||||
/* 5.2.3 Definition of nextbits_bytealigned() function */
|
||||
skip = vop->size % 8;
|
||||
remaining = gst_bit_reader_get_remaining (&br);
|
||||
if (!skip) {
|
||||
if (remaining > 8 && br.data[br.byte + 1] == 0x7f)
|
||||
skip = 8;
|
||||
}
|
||||
|
||||
/* Align to next byte */
|
||||
if (!gst_bit_reader_skip (&br, skip))
|
||||
goto failed;
|
||||
|
||||
markersize = compute_resync_marker_size (vop);
|
||||
|
||||
CHECK_REMAINING (&br, markersize);
|
||||
|
||||
if (gst_bit_reader_peek_bits_uint32_unchecked (&br, markersize) != 0x01)
|
||||
goto failed;
|
||||
|
||||
GST_DEBUG ("Resync code found at %i", br.byte);
|
||||
|
||||
packet->offset = br.byte;
|
||||
packet->type = GST_MPEG4_RESYNC;
|
||||
packet->size = 0;
|
||||
packet->marker_size = markersize;
|
||||
|
||||
return GST_MPEG4_PARSER_OK;
|
||||
|
||||
failed:
|
||||
GST_DEBUG ("No resync found in this buffer");
|
||||
|
||||
return GST_MPEG4_PARSER_NO_PACKET;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mpeg4_parse_video_packet_header:
|
||||
* @videopackethdr: The #GstMpeg4VideoPacketHdr structure to fill
|
||||
|
@ -1553,7 +1598,7 @@ gst_mpeg4_parse_video_packet_header (GstMpeg4VideoPacketHdr * videopackethdr,
|
|||
g_return_val_if_fail (videopackethdr != NULL, GST_MPEG4_PARSER_ERROR);
|
||||
g_return_val_if_fail (vol != NULL, GST_MPEG4_PARSER_ERROR);
|
||||
|
||||
markersize = compute_resync_marker_size (vop);
|
||||
markersize = compute_resync_marker_size (vop, NULL, NULL);
|
||||
|
||||
CHECK_REMAINING (&br, markersize);
|
||||
|
||||
|
|
|
@ -515,7 +515,6 @@ struct _GstMpeg4VideoPacketHdr {
|
|||
* @offset: offset of the start of the packet (without the 3 bytes startcode), but
|
||||
* including the #GstMpeg4StartCode byte.
|
||||
* @size: The size in bytes of the packet or %G_MAXUINT if the end wasn't found.
|
||||
* Set to 0 if type == GST_MPEG4_RESYNC.
|
||||
* @marker_size: The size in bit of the resync marker.
|
||||
*
|
||||
* A structure that contains the type of a packet, its offset and its size
|
||||
|
@ -537,6 +536,7 @@ GstMpeg4ParseResult gst_h263_parse (GstMpeg4Packet * packet,
|
|||
|
||||
GstMpeg4ParseResult gst_mpeg4_parse (GstMpeg4Packet * packet,
|
||||
gboolean skip_user_data,
|
||||
GstMpeg4VideoObjectPlane *vop,
|
||||
const guint8 * data, guint offset,
|
||||
gsize size);
|
||||
|
||||
|
@ -568,11 +568,6 @@ GstMpeg4ParseResult
|
|||
gst_mpeg4_parse_video_plane_short_header (GstMpeg4VideoPlaneShortHdr * shorthdr,
|
||||
const guint8 * data, gsize size);
|
||||
|
||||
GstMpeg4ParseResult
|
||||
gst_mpeg4_next_resync (GstMpeg4Packet * packet,
|
||||
const GstMpeg4VideoObjectPlane * vop,
|
||||
const guint8 *data, gsize size);
|
||||
|
||||
GstMpeg4ParseResult
|
||||
gst_mpeg4_parse_video_packet_header (GstMpeg4VideoPacketHdr * videopackethdr,
|
||||
GstMpeg4VideoObjectLayer * vol,
|
||||
|
|
|
@ -393,7 +393,7 @@ retry:
|
|||
}
|
||||
|
||||
/* didn't find anything that looks like a sync word, skip */
|
||||
switch (gst_mpeg4_parse (&packet, TRUE, data, off, size)) {
|
||||
switch (gst_mpeg4_parse (&packet, TRUE, NULL, data, off, size)) {
|
||||
case (GST_MPEG4_PARSER_NO_PACKET):
|
||||
case (GST_MPEG4_PARSER_ERROR):
|
||||
*skipsize = size - 3;
|
||||
|
@ -437,7 +437,7 @@ next:
|
|||
off++;
|
||||
|
||||
/* so now we have start code at start of data; locate next packet */
|
||||
switch (gst_mpeg4_parse (&packet, TRUE, data, off, size)) {
|
||||
switch (gst_mpeg4_parse (&packet, TRUE, NULL, data, off, size)) {
|
||||
case (GST_MPEG4_PARSER_NO_PACKET_END):
|
||||
ret = gst_mpeg4vparse_process_sc (mp4vparse, &packet, size);
|
||||
if (ret)
|
||||
|
@ -638,7 +638,7 @@ gst_mpeg4vparse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
* whether sucessful or not */
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
res = gst_mpeg4_parse (&packet, TRUE, data, 0, size);
|
||||
res = gst_mpeg4_parse (&packet, TRUE, NULL, data, 0, size);
|
||||
|
||||
while (res == GST_MPEG4_PARSER_OK || res == GST_MPEG4_PARSER_NO_PACKET_END) {
|
||||
|
||||
|
@ -646,7 +646,7 @@ gst_mpeg4vparse_set_caps (GstBaseParse * parse, GstCaps * caps)
|
|||
packet.type <= GST_MPEG4_VIDEO_LAYER_LAST)
|
||||
mp4vparse->vol_offset = packet.offset;
|
||||
|
||||
res = gst_mpeg4_parse (&packet, TRUE, data, packet.offset, size);
|
||||
res = gst_mpeg4_parse (&packet, TRUE, NULL, data, packet.offset, size);
|
||||
}
|
||||
|
||||
/* And take it as config */
|
||||
|
|
Loading…
Reference in a new issue