diff options
Diffstat (limited to 'gst-libs/gst/codecparsers/gsth264parser.c')
-rw-r--r-- | gst-libs/gst/codecparsers/gsth264parser.c | 343 |
1 files changed, 5 insertions, 338 deletions
diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 52f2bf739..506946d24 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -84,6 +84,7 @@ # include "config.h" #endif +#include "nalutils.h" #include "gsth264parser.h" #include <gst/base/gstbytereader.h> @@ -170,289 +171,6 @@ static PAR aspect_ratios[17] = { {2, 1} }; -/* Compute Ceil(Log2(v)) */ -/* Derived from branchless code for integer log2(v) from: - <http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog> */ -static guint -ceil_log2 (guint32 v) -{ - guint r, shift; - - v--; - r = (v > 0xFFFF) << 4; - v >>= r; - shift = (v > 0xFF) << 3; - v >>= shift; - r |= shift; - shift = (v > 0xF) << 2; - v >>= shift; - r |= shift; - shift = (v > 0x3) << 1; - v >>= shift; - r |= shift; - r |= (v >> 1); - return r + 1; -} - -/****** Nal parser ******/ - -typedef struct -{ - const guint8 *data; - guint size; - - guint n_epb; /* Number of emulation prevention bytes */ - guint byte; /* Byte position */ - guint bits_in_cache; /* bitpos in the cache of next bit */ - guint8 first_byte; - guint64 cache; /* cached bytes */ -} NalReader; - -static void -nal_reader_init (NalReader * nr, const guint8 * data, guint size) -{ - nr->data = data; - nr->size = size; - nr->n_epb = 0; - - nr->byte = 0; - nr->bits_in_cache = 0; - /* fill with something other than 0 to detect emulation prevention bytes */ - nr->first_byte = 0xff; - nr->cache = 0xff; -} - -static inline gboolean -nal_reader_read (NalReader * nr, guint nbits) -{ - if (G_UNLIKELY (nr->byte * 8 + (nbits - nr->bits_in_cache) > nr->size * 8)) { - GST_DEBUG ("Can not read %u bits, bits in cache %u, Byte * 8 %u, size in " - "bits %u", nbits, nr->bits_in_cache, nr->byte * 8, nr->size * 8); - return FALSE; - } - - while (nr->bits_in_cache < nbits) { - guint8 byte; - gboolean check_three_byte; - - check_three_byte = TRUE; - next_byte: - if (G_UNLIKELY (nr->byte >= nr->size)) - return FALSE; - - byte = nr->data[nr->byte++]; - - /* check if the byte is a emulation_prevention_three_byte */ - if (check_three_byte && byte == 0x03 && nr->first_byte == 0x00 && - ((nr->cache & 0xff) == 0)) { - /* next byte goes unconditionally to the cache, even if it's 0x03 */ - check_three_byte = FALSE; - nr->n_epb++; - goto next_byte; - } - nr->cache = (nr->cache << 8) | nr->first_byte; - nr->first_byte = byte; - nr->bits_in_cache += 8; - } - - return TRUE; -} - -static inline gboolean -nal_reader_skip (NalReader * nr, guint nbits) -{ - if (G_UNLIKELY (!nal_reader_read (nr, nbits))) - return FALSE; - - nr->bits_in_cache -= nbits; - - return TRUE; -} - -static inline gboolean -nal_reader_skip_to_next_byte (NalReader * nr) -{ - if (nr->bits_in_cache == 0) { - if (G_LIKELY ((nr->size - nr->byte) > 0)) - nr->byte++; - else - return FALSE; - } - - nr->bits_in_cache = 0; - - return TRUE; -} - -static inline guint -nal_reader_get_pos (const NalReader * nr) -{ - return nr->byte * 8 - nr->bits_in_cache; -} - -static inline guint -nal_reader_get_remaining (const NalReader * nr) -{ - return (nr->size - nr->byte) * 8 + nr->bits_in_cache; -} - -static inline guint -nal_reader_get_epb_count (const NalReader * nr) -{ - return nr->n_epb; -} - -#define GST_NAL_READER_READ_BITS(bits) \ -static gboolean \ -nal_reader_get_bits_uint##bits (NalReader *nr, guint##bits *val, guint nbits) \ -{ \ - guint shift; \ - \ - if (!nal_reader_read (nr, nbits)) \ - return FALSE; \ - \ - /* bring the required bits down and truncate */ \ - shift = nr->bits_in_cache - nbits; \ - *val = nr->first_byte >> shift; \ - \ - *val |= nr->cache << (8 - shift); \ - /* mask out required bits */ \ - if (nbits < bits) \ - *val &= ((guint##bits)1 << nbits) - 1; \ - \ - nr->bits_in_cache = shift; \ - \ - return TRUE; \ -} \ - -GST_NAL_READER_READ_BITS (8); -GST_NAL_READER_READ_BITS (16); -GST_NAL_READER_READ_BITS (32); - -#define GST_NAL_READER_PEAK_BITS(bits) \ -static gboolean \ -nal_reader_peek_bits_uint##bits (const NalReader *nr, guint##bits *val, guint nbits) \ -{ \ - NalReader tmp; \ - \ - tmp = *nr; \ - return nal_reader_get_bits_uint##bits (&tmp, val, nbits); \ -} - -GST_NAL_READER_PEAK_BITS (8); - -static gboolean -nal_reader_get_ue (NalReader * nr, guint32 * val) -{ - guint i = 0; - guint8 bit; - guint32 value; - - if (G_UNLIKELY (!nal_reader_get_bits_uint8 (nr, &bit, 1))) { - - return FALSE; - } - - while (bit == 0) { - i++; - if G_UNLIKELY - ((!nal_reader_get_bits_uint8 (nr, &bit, 1))) - return FALSE; - } - - if (G_UNLIKELY (i > 32)) - return FALSE; - - if (G_UNLIKELY (!nal_reader_get_bits_uint32 (nr, &value, i))) - return FALSE; - - *val = (1 << i) - 1 + value; - - return TRUE; -} - -static inline gboolean -nal_reader_get_se (NalReader * nr, gint32 * val) -{ - guint32 value; - - if (G_UNLIKELY (!nal_reader_get_ue (nr, &value))) - return FALSE; - - if (value % 2) - *val = (value / 2) + 1; - else - *val = -(value / 2); - - return TRUE; -} - -#define CHECK_ALLOWED(val, min, max) { \ - if (val < min || val > max) { \ - GST_WARNING ("value not in allowed range. value: %d, range %d-%d", \ - val, min, max); \ - goto error; \ - } \ -} - -#define READ_UINT8(nr, val, nbits) { \ - if (!nal_reader_get_bits_uint8 (nr, &val, nbits)) { \ - GST_WARNING ("failed to read uint8, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UINT16(nr, val, nbits) { \ - if (!nal_reader_get_bits_uint16 (nr, &val, nbits)) { \ - GST_WARNING ("failed to read uint16, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UINT32(nr, val, nbits) { \ - if (!nal_reader_get_bits_uint32 (nr, &val, nbits)) { \ - GST_WARNING ("failed to read uint32, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UINT64(nr, val, nbits) { \ - if (!nal_reader_get_bits_uint64 (nr, &val, nbits)) { \ - GST_WARNING ("failed to read uint32, nbits: %d", nbits); \ - goto error; \ - } \ -} - -#define READ_UE(nr, val) { \ - if (!nal_reader_get_ue (nr, &val)) { \ - GST_WARNING ("failed to read UE"); \ - goto error; \ - } \ -} - -#define READ_UE_ALLOWED(nr, val, min, max) { \ - guint32 tmp; \ - READ_UE (nr, tmp); \ - CHECK_ALLOWED (tmp, min, max); \ - val = tmp; \ -} - -#define READ_SE(nr, val) { \ - if (!nal_reader_get_se (nr, &val)) { \ - GST_WARNING ("failed to read SE"); \ - goto error; \ - } \ -} - -#define READ_SE_ALLOWED(nr, val, min, max) { \ - gint32 tmp; \ - READ_SE (nr, tmp); \ - CHECK_ALLOWED (tmp, min, max); \ - val = tmp; \ -} - -/*********** end of nal parser ***************/ - /***** Utils ****/ #define EXTENDED_SAR 255 @@ -494,57 +212,6 @@ set_nalu_datas (GstH264NalUnit * nalu) GST_DEBUG ("Nal type %u, ref_idc %u", nalu->type, nalu->ref_idc); } -static inline gint -scan_for_start_codes (const guint8 * data, guint size) -{ - GstByteReader br; - gst_byte_reader_init (&br, data, size); - - /* NALU not empty, so we can at least expect 1 (even 2) bytes following sc */ - return gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100, - 0, size); -} - -static gboolean -gst_h264_parser_byte_aligned (NalReader * nr) -{ - if (nr->bits_in_cache != 0) - return FALSE; - return TRUE; -} - -static gboolean -gst_h264_parser_more_data (NalReader * nr) -{ - guint remaining; - - remaining = nal_reader_get_remaining (nr); - if (remaining == 0) - return FALSE; - - if (remaining <= 8) { - guint8 rbsp_stop_one_bit; - - if (!nal_reader_peek_bits_uint8 (nr, &rbsp_stop_one_bit, 1)) - return FALSE; - - if (rbsp_stop_one_bit == 1) { - guint8 zero_bits; - - if (remaining == 1) - return FALSE; - - if (!nal_reader_peek_bits_uint8 (nr, &zero_bits, remaining)) - return FALSE; - - if ((zero_bits - (1 << (remaining - 1))) == 0) - return FALSE; - } - } - - return TRUE; -} - /****** Parsing functions *****/ static gboolean @@ -1221,13 +888,13 @@ gst_h264_parser_parse_sei_message (GstH264NalParser * nalparser, /* When SEI message doesn't end at byte boundary, * check remaining bits fit the specification. */ - if (!gst_h264_parser_byte_aligned (nr)) { + if (!gst_nal_reader_is_byte_aligned (nr)) { guint8 bit_equal_to_one; READ_UINT8 (nr, bit_equal_to_one, 1); if (!bit_equal_to_one) GST_WARNING ("Bit non equal to one."); - while (!gst_h264_parser_byte_aligned (nr)) { + while (!gst_nal_reader_is_byte_aligned (nr)) { guint8 bit_equal_to_zero; READ_UINT8 (nr, bit_equal_to_zero, 1); if (bit_equal_to_zero) @@ -1791,7 +1458,7 @@ gst_h264_parse_pps (GstH264NalParser * nalparser, GstH264NalUnit * nalu, READ_UINT8 (&nr, pps->constrained_intra_pred_flag, 1); READ_UINT8 (&nr, pps->redundant_pic_cnt_present_flag, 1); - if (!gst_h264_parser_more_data (&nr)) + if (!gst_nal_reader_has_more_data (&nr)) goto done; READ_UINT8 (&nr, pps->transform_8x8_mode_flag, 1); @@ -2063,7 +1730,7 @@ gst_h264_parser_parse_sei (GstH264NalParser * nalparser, GstH264NalUnit * nalu, g_array_append_val (*messages, sei); else break; - } while (gst_h264_parser_more_data (&nr)); + } while (gst_nal_reader_has_more_data (&nr)); return res; } |