[FFmpeg-cvslog] h264: Refactor decode_nal_units
Luca Barbato
git at videolan.org
Mon Apr 7 04:04:56 CEST 2014
ffmpeg | branch: master | Luca Barbato <lu_zero at gentoo.org> | Sat Apr 5 00:41:12 2014 +0000| [e10fd08aa7fbe8645545ad2e8721f0ed03c8e06a] | committer: Janne Grunau
h264: Refactor decode_nal_units
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e10fd08aa7fbe8645545ad2e8721f0ed03c8e06a
---
libavcodec/h264.c | 181 ++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 122 insertions(+), 59 deletions(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 9a96937..c4ce278 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -1281,6 +1281,116 @@ int ff_set_ref_count(H264Context *h)
return 0;
}
+static int find_start_code(const uint8_t *buf, int buf_size,
+ int buf_index, int next_avc)
+{
+ // start code prefix search
+ for (; buf_index + 3 < next_avc; buf_index++)
+ // This should always succeed in the first iteration.
+ if (buf[buf_index] == 0 &&
+ buf[buf_index + 1] == 0 &&
+ buf[buf_index + 2] == 1)
+ break;
+
+ if (buf_index + 3 >= buf_size)
+ return buf_size;
+
+ return buf_index + 3;
+}
+
+static int get_avc_nalsize(H264Context *h, const uint8_t *buf,
+ int buf_size, int *buf_index)
+{
+ int i, nalsize = 0;
+
+ if (*buf_index >= buf_size - h->nal_length_size)
+ return -1;
+
+ for (i = 0; i < h->nal_length_size; i++)
+ nalsize = (nalsize << 8) | buf[(*buf_index)++];
+ if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
+ av_log(h->avctx, AV_LOG_ERROR,
+ "AVC: nal size %d\n", nalsize);
+ return -1;
+ }
+ return nalsize;
+}
+
+static int get_bit_length(H264Context *h, const uint8_t *buf,
+ const uint8_t *ptr, int dst_length,
+ int i, int next_avc)
+{
+ if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc &&
+ buf[i] == 0x00 && buf[i + 1] == 0x00 &&
+ buf[i + 2] == 0x01 && buf[i + 3] == 0xE0)
+ h->workaround_bugs |= FF_BUG_TRUNCATED;
+
+ if (!(h->workaround_bugs & FF_BUG_TRUNCATED))
+ while (dst_length > 0 && ptr[dst_length - 1] == 0)
+ dst_length--;
+
+ if (!dst_length)
+ return 0;
+
+ return 8 * dst_length - decode_rbsp_trailing(h, ptr + dst_length - 1);
+}
+
+static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int buf_size)
+{
+ int next_avc = h->is_avc ? 0 : buf_size;
+ int nal_index = 0;
+ int buf_index = 0;
+ int nals_needed = 0;
+
+ while(1) {
+ int nalsize = 0;
+ int dst_length, bit_length, consumed;
+ const uint8_t *ptr;
+
+ if (buf_index >= next_avc) {
+ nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
+ if (nalsize < 0)
+ break;
+ next_avc = buf_index + nalsize;
+ } else {
+ buf_index = find_start_code(buf, buf_size, buf_index, next_avc);
+ if (buf_index >= buf_size)
+ break;
+ }
+
+ ptr = ff_h264_decode_nal(h, buf + buf_index, &dst_length, &consumed,
+ next_avc - buf_index);
+
+ if (ptr == NULL || dst_length < 0)
+ return AVERROR_INVALIDDATA;
+
+ buf_index += consumed;
+
+ bit_length = get_bit_length(h, buf, ptr, dst_length,
+ buf_index, next_avc);
+ nal_index++;
+
+ /* packets can sometimes contain multiple PPS/SPS,
+ * e.g. two PAFF field pictures in one packet, or a demuxer
+ * which splits NALs strangely if so, when frame threading we
+ * can't start the next thread until we've read all of them */
+ switch (h->nal_unit_type) {
+ case NAL_SPS:
+ case NAL_PPS:
+ nals_needed = nal_index;
+ break;
+ case NAL_DPA:
+ case NAL_IDR_SLICE:
+ case NAL_SLICE:
+ init_get_bits(&h->gb, ptr, bit_length);
+ if (!get_ue_golomb(&h->gb))
+ nals_needed = nal_index;
+ }
+ }
+
+ return nals_needed;
+}
+
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
int parse_extradata)
{
@@ -1289,7 +1399,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
int buf_index;
unsigned context_count;
int next_avc;
- int pass = !(avctx->active_thread_type & FF_THREAD_FRAME);
int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts
int nal_index;
int ret = 0;
@@ -1302,7 +1411,10 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
ff_h264_reset_sei(h);
}
- for (; pass <= 1; pass++) {
+ if (avctx->active_thread_type & FF_THREAD_FRAME)
+ nals_needed = get_last_needed_nal(h, buf, buf_size);
+
+ {
buf_index = 0;
context_count = 0;
next_avc = h->is_avc ? 0 : buf_size;
@@ -1312,38 +1424,18 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
int dst_length;
int bit_length;
const uint8_t *ptr;
- int i, nalsize = 0;
+ int nalsize = 0;
int err;
if (buf_index >= next_avc) {
- if (buf_index >= buf_size - h->nal_length_size)
- break;
- nalsize = 0;
- for (i = 0; i < h->nal_length_size; i++)
- nalsize = (nalsize << 8) | buf[buf_index++];
- if (nalsize <= 0 || nalsize > buf_size - buf_index) {
- av_log(h->avctx, AV_LOG_ERROR,
- "AVC: nal size %d\n", nalsize);
+ nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
+ if (nalsize < 0)
break;
- }
next_avc = buf_index + nalsize;
} else {
- // start code prefix search
- for (; buf_index + 3 < next_avc; buf_index++)
- // This should always succeed in the first iteration.
- if (buf[buf_index] == 0 &&
- buf[buf_index + 1] == 0 &&
- buf[buf_index + 2] == 1)
- break;
-
- if (buf_index + 3 >= buf_size) {
- buf_index = buf_size;
+ buf_index = find_start_code(buf, buf_size, buf_index, next_avc);
+ if (buf_index >= buf_size)
break;
- }
-
- buf_index += 3;
- if (buf_index >= next_avc)
- continue;
}
hx = h->thread_context[context_count];
@@ -1354,18 +1446,9 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
ret = -1;
goto end;
}
- i = buf_index + consumed;
- if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc &&
- buf[i] == 0x00 && buf[i + 1] == 0x00 &&
- buf[i + 2] == 0x01 && buf[i + 3] == 0xE0)
- h->workaround_bugs |= FF_BUG_TRUNCATED;
-
- if (!(h->workaround_bugs & FF_BUG_TRUNCATED))
- while (dst_length > 0 && ptr[dst_length - 1] == 0)
- dst_length--;
- bit_length = !dst_length ? 0
- : (8 * dst_length -
- decode_rbsp_trailing(h, ptr + dst_length - 1));
+
+ bit_length = get_bit_length(h, buf, ptr, dst_length,
+ buf_index + consumed, next_avc);
if (h->avctx->debug & FF_DEBUG_STARTCODE)
av_log(h->avctx, AV_LOG_DEBUG,
@@ -1380,26 +1463,6 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
buf_index += consumed;
nal_index++;
- if (pass == 0) {
- /* packets can sometimes contain multiple PPS/SPS,
- * e.g. two PAFF field pictures in one packet, or a demuxer
- * which splits NALs strangely if so, when frame threading we
- * can't start the next thread until we've read all of them */
- switch (hx->nal_unit_type) {
- case NAL_SPS:
- case NAL_PPS:
- nals_needed = nal_index;
- break;
- case NAL_DPA:
- case NAL_IDR_SLICE:
- case NAL_SLICE:
- init_get_bits(&hx->gb, ptr, bit_length);
- if (!get_ue_golomb(&hx->gb))
- nals_needed = nal_index;
- }
- continue;
- }
-
if (avctx->skip_frame >= AVDISCARD_NONREF &&
h->nal_ref_idc == 0 &&
h->nal_unit_type != NAL_SEI)
More information about the ffmpeg-cvslog
mailing list