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:
Thibault Saunier 2011-11-08 10:44:11 -03:00
parent 5555b5fa9d
commit e1bacb4813
3 changed files with 117 additions and 77 deletions

View file

@ -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);

View file

@ -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,

View file

@ -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 */