ffmpeg | branch: master | James Almer <[email protected]> | Fri Oct 20 19:04:53 2017 -0300| [07cf202614a89aac96e30d9b5295c85b14b87ebe] | committer: James Almer
Merge commit '83b2b34d06e74cc8775ba3d833f9782505e17539' * commit '83b2b34d06e74cc8775ba3d833f9782505e17539': h2645_parse: use the bytestream2 API for packet splitting Merged-by: James Almer <[email protected]> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=07cf202614a89aac96e30d9b5295c85b14b87ebe --- libavcodec/h2645_parse.c | 85 ++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index b0d9ff66f0..3fbbaf4d29 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -26,6 +26,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" +#include "bytestream.h" #include "hevc.h" #include "h2645_parse.h" @@ -247,60 +248,74 @@ static int h264_parse_nal_header(H2645NAL *nal, void *logctx) return 1; } +static int find_next_start_code(const uint8_t *buf, const uint8_t *next_avc) +{ + int i = 0; + + if (buf + 3 >= next_avc) + return next_avc - buf; + + while (buf + i + 3 < next_avc) { + if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) + break; + i++; + } + return i + 3; +} + int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, void *logctx, int is_nalff, int nal_length_size, enum AVCodecID codec_id, int small_padding) { + GetByteContext bc; int consumed, ret = 0; - const uint8_t *next_avc = is_nalff ? buf : buf + length; + int next_avc = is_nalff ? 0 : length; + + bytestream2_init(&bc, buf, length); pkt->nb_nals = 0; - while (length >= 4) { + while (bytestream2_get_bytes_left(&bc) >= 4) { H2645NAL *nal; int extract_length = 0; int skip_trailing_zeros = 1; - if (buf == next_avc) { + if (bytestream2_tell(&bc) == next_avc) { int i = 0; extract_length = get_nalsize(nal_length_size, - buf, length, &i, logctx); + bc.buffer, bytestream2_get_bytes_left(&bc), &i, logctx); if (extract_length < 0) return extract_length; - buf += nal_length_size; - length -= nal_length_size; + bytestream2_skip(&bc, nal_length_size); - next_avc = buf + extract_length; + next_avc = bytestream2_tell(&bc) + extract_length; } else { - if (buf > next_avc) + int buf_index; + + if (bytestream2_tell(&bc) > next_avc) av_log(logctx, AV_LOG_WARNING, "Exceeded next NALFF position, re-syncing.\n"); /* search start code */ - while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { - ++buf; - --length; - if (length < 4) { - if (pkt->nb_nals > 0) { - // No more start codes: we discarded some irrelevant - // bytes at the end of the packet. - return 0; - } else { - av_log(logctx, AV_LOG_ERROR, "No start code is found.\n"); - return AVERROR_INVALIDDATA; - } - } else if (buf >= (next_avc - 3)) - break; + buf_index = find_next_start_code(bc.buffer, buf + next_avc); + + bytestream2_skip(&bc, buf_index); + + if (!bytestream2_get_bytes_left(&bc)) { + if (pkt->nb_nals > 0) { + // No more start codes: we discarded some irrelevant + // bytes at the end of the packet. + return 0; + } else { + av_log(logctx, AV_LOG_ERROR, "No start code is found.\n"); + return AVERROR_INVALIDDATA; + } } - buf += 3; - length -= 3; - extract_length = FFMIN(length, next_avc - buf); + extract_length = FFMIN(bytestream2_get_bytes_left(&bc), next_avc - bytestream2_tell(&bc)); - if (buf >= next_avc) { + if (bytestream2_tell(&bc) >= next_avc) { /* skip to the start of the next NAL */ - int offset = next_avc - buf; - buf += offset; - length -= offset; + bytestream2_skip(&bc, next_avc - bytestream2_tell(&bc)); continue; } } @@ -326,7 +341,7 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, } nal = &pkt->nals[pkt->nb_nals]; - consumed = ff_h2645_extract_rbsp(buf, extract_length, nal, small_padding); + consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, nal, small_padding); if (consumed < 0) return consumed; @@ -337,10 +352,11 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, pkt->nb_nals++; + bytestream2_skip(&bc, consumed); + /* see commit 3566042a0 */ - if (consumed < length - 3 && - buf[consumed] == 0x00 && buf[consumed + 1] == 0x00 && - buf[consumed + 2] == 0x01 && buf[consumed + 3] == 0xE0) + if (bytestream2_get_bytes_left(&bc) >= 4 && + bytestream2_peek_be32(&bc) == 0x000001E0) skip_trailing_zeros = 0; nal->size_bits = get_bit_length(nal, skip_trailing_zeros); @@ -360,9 +376,6 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, } pkt->nb_nals--; } - - buf += consumed; - length -= consumed; } return 0; ====================================================================== diff --cc libavcodec/h2645_parse.c index b0d9ff66f0,b507b19ecb..3fbbaf4d29 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@@ -26,7 -26,7 +26,8 @@@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" + #include "bytestream.h" +#include "hevc.h" #include "h2645_parse.h" int ff_h2645_extract_rbsp(const uint8_t *src, int length, @@@ -247,61 -196,81 +248,75 @@@ static int h264_parse_nal_header(H2645N return 1; } + static int find_next_start_code(const uint8_t *buf, const uint8_t *next_avc) + { + int i = 0; + + if (buf + 3 >= next_avc) + return next_avc - buf; + + while (buf + i + 3 < next_avc) { + if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) + break; + i++; + } + return i + 3; + } + int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, void *logctx, int is_nalff, int nal_length_size, - enum AVCodecID codec_id) + enum AVCodecID codec_id, int small_padding) { + GetByteContext bc; int consumed, ret = 0; - const uint8_t *next_avc = is_nalff ? buf : buf + length; - size_t next_avc = is_nalff ? 0 : length; ++ int next_avc = is_nalff ? 0 : length; + + bytestream2_init(&bc, buf, length); pkt->nb_nals = 0; - while (length >= 4) { + while (bytestream2_get_bytes_left(&bc) >= 4) { H2645NAL *nal; int extract_length = 0; int skip_trailing_zeros = 1; - if (buf == next_avc) { - /* - * Only parse an AVC1 length field if one is expected at the current - * buffer position. There are unfortunately streams with multiple - * NAL units covered by the length field. Those NAL units are delimited - * by Annex B start code prefixes. ff_h2645_extract_rbsp() detects it - * correctly and consumes only the first NAL unit. The additional NAL - * units are handled here in the Annex B parsing code. - */ + if (bytestream2_tell(&bc) == next_avc) { - int i; - for (i = 0; i < nal_length_size; i++) - extract_length = (extract_length << 8) | bytestream2_get_byte(&bc); - - if (extract_length > bytestream2_get_bytes_left(&bc)) { - av_log(logctx, AV_LOG_ERROR, - "Invalid NAL unit size (%d > %d).\n", - extract_length, bytestream2_get_bytes_left(&bc)); - return AVERROR_INVALIDDATA; - } - // keep track of the next AVC1 length field + int i = 0; + extract_length = get_nalsize(nal_length_size, - buf, length, &i, logctx); ++ bc.buffer, bytestream2_get_bytes_left(&bc), &i, logctx); + if (extract_length < 0) + return extract_length; + - buf += nal_length_size; - length -= nal_length_size; ++ bytestream2_skip(&bc, nal_length_size); + - next_avc = buf + extract_length; + next_avc = bytestream2_tell(&bc) + extract_length; } else { - if (buf > next_avc) - /* - * expected to return immediately except for streams with mixed - * NAL unit coding - */ - int buf_index = find_next_start_code(bc.buffer, buf + next_avc); ++ int buf_index; ++ ++ if (bytestream2_tell(&bc) > next_avc) + av_log(logctx, AV_LOG_WARNING, "Exceeded next NALFF position, re-syncing.\n"); + + /* search start code */ - while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { - ++buf; - --length; - if (length < 4) { - if (pkt->nb_nals > 0) { - // No more start codes: we discarded some irrelevant - // bytes at the end of the packet. - return 0; - } else { - av_log(logctx, AV_LOG_ERROR, "No start code is found.\n"); - return AVERROR_INVALIDDATA; - } - } else if (buf >= (next_avc - 3)) - break; ++ buf_index = find_next_start_code(bc.buffer, buf + next_avc); + + bytestream2_skip(&bc, buf_index); + - /* - * break if an AVC1 length field is expected at the current buffer - * position - */ - if (bytestream2_tell(&bc) == next_avc) - continue; ++ if (!bytestream2_get_bytes_left(&bc)) { ++ if (pkt->nb_nals > 0) { ++ // No more start codes: we discarded some irrelevant ++ // bytes at the end of the packet. ++ return 0; ++ } else { ++ av_log(logctx, AV_LOG_ERROR, "No start code is found.\n"); ++ return AVERROR_INVALIDDATA; ++ } + } + - buf += 3; - length -= 3; - extract_length = FFMIN(length, next_avc - buf); ++ extract_length = FFMIN(bytestream2_get_bytes_left(&bc), next_avc - bytestream2_tell(&bc)); - if (buf >= next_avc) { - if (bytestream2_get_bytes_left(&bc) > 0) { - extract_length = bytestream2_get_bytes_left(&bc); - } else if (pkt->nb_nals == 0) { - av_log(logctx, AV_LOG_ERROR, "No NAL unit found\n"); - return AVERROR_INVALIDDATA; - } else { - break; ++ if (bytestream2_tell(&bc) >= next_avc) { + /* skip to the start of the next NAL */ - int offset = next_avc - buf; - buf += offset; - length -= offset; ++ bytestream2_skip(&bc, next_avc - bytestream2_tell(&bc)); + continue; } } @@@ -314,33 -282,20 +329,34 @@@ pkt->nals = tmp; memset(pkt->nals + pkt->nals_allocated, 0, - (new_size - pkt->nals_allocated) * sizeof(*tmp)); + (new_size - pkt->nals_allocated) * sizeof(*pkt->nals)); + + nal = &pkt->nals[pkt->nb_nals]; + nal->skipped_bytes_pos_size = 1024; // initial buffer size + nal->skipped_bytes_pos = av_malloc_array(nal->skipped_bytes_pos_size, sizeof(*nal->skipped_bytes_pos)); + if (!nal->skipped_bytes_pos) + return AVERROR(ENOMEM); + pkt->nals_allocated = new_size; } - nal = &pkt->nals[pkt->nb_nals++]; + nal = &pkt->nals[pkt->nb_nals]; - consumed = ff_h2645_extract_rbsp(buf, extract_length, nal, small_padding); - consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, nal); ++ consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, nal, small_padding); if (consumed < 0) return consumed; + if (is_nalff && (extract_length != consumed) && extract_length) + av_log(logctx, AV_LOG_DEBUG, + "NALFF: Consumed only %d bytes instead of %d\n", + consumed, extract_length); + + pkt->nb_nals++; + + bytestream2_skip(&bc, consumed); + /* see commit 3566042a0 */ - if (consumed < length - 3 && - buf[consumed] == 0x00 && buf[consumed + 1] == 0x00 && - buf[consumed + 2] == 0x01 && buf[consumed + 3] == 0xE0) + if (bytestream2_get_bytes_left(&bc) >= 4 && + bytestream2_peek_be32(&bc) == 0x000001E0) skip_trailing_zeros = 0; nal->size_bits = get_bit_length(nal, skip_trailing_zeros); _______________________________________________ ffmpeg-cvslog mailing list [email protected] http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog
