diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2015-07-09 05:04:13 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2015-07-09 05:06:48 +0200 |
commit | 07ae8fa20ef202206157efebf0a09db9a9cb9634 (patch) | |
tree | 75e15cb455b62eac5a0dff6e95cd90ffe2a99e08 /libavcodec | |
parent | 1dacf26964c9a65380ca615d1fc09302218a539e (diff) | |
parent | 69ab9f53f901eac6a649e22d28cf093357870627 (diff) | |
download | ffmpeg-07ae8fa20ef202206157efebf0a09db9a9cb9634.tar.gz |
Merge commit '69ab9f53f901eac6a649e22d28cf093357870627'
* commit '69ab9f53f901eac6a649e22d28cf093357870627':
hevc: split bitstream unescaping to a separate file
Conflicts:
libavcodec/Makefile
libavcodec/hevc.c
See: afa93d198aaf2cc661c4df6d4095cd030265d30a
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/Makefile | 2 | ||||
-rw-r--r-- | libavcodec/hevc.c | 123 | ||||
-rw-r--r-- | libavcodec/hevc.h | 9 | ||||
-rw-r--r-- | libavcodec/hevc_parse.c | 145 |
4 files changed, 156 insertions, 123 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index db8d818137..a062833ffc 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -285,7 +285,7 @@ OBJS-$(CONFIG_HAP_DECODER) += hapdec.o OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o OBJS-$(CONFIG_HEVC_DECODER) += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ - hevcdsp.o hevc_filter.o + hevcdsp.o hevc_filter.o hevc_parse.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ canopus.o diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index f7f0552498..38734f017d 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -2786,119 +2786,6 @@ fail: return 0; } -/* FIXME: This is adapted from ff_h264_decode_nal, avoiding duplication - * between these functions would be nice. */ -int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length, - HEVCNAL *nal) -{ - int i, si, di; - uint8_t *dst; - - s->skipped_bytes = 0; -#define STARTCODE_TEST \ - if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ - if (src[i + 2] != 3) { \ - /* startcode, so we must be past the end */ \ - length = i; \ - } \ - break; \ - } -#if HAVE_FAST_UNALIGNED -#define FIND_FIRST_ZERO \ - if (i > 0 && !src[i]) \ - i--; \ - while (src[i]) \ - i++ -#if HAVE_FAST_64BIT - for (i = 0; i + 1 < length; i += 9) { - if (!((~AV_RN64A(src + i) & - (AV_RN64A(src + i) - 0x0100010001000101ULL)) & - 0x8000800080008080ULL)) - continue; - FIND_FIRST_ZERO; - STARTCODE_TEST; - i -= 7; - } -#else - for (i = 0; i + 1 < length; i += 5) { - if (!((~AV_RN32A(src + i) & - (AV_RN32A(src + i) - 0x01000101U)) & - 0x80008080U)) - continue; - FIND_FIRST_ZERO; - STARTCODE_TEST; - i -= 3; - } -#endif /* HAVE_FAST_64BIT */ -#else - for (i = 0; i + 1 < length; i += 2) { - if (src[i]) - continue; - if (i > 0 && src[i - 1] == 0) - i--; - STARTCODE_TEST; - } -#endif /* HAVE_FAST_UNALIGNED */ - - if (i >= length - 1) { // no escaped 0 - nal->data = - nal->raw_data = src; - nal->size = - nal->raw_size = length; - return length; - } - - av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size, - length + FF_INPUT_BUFFER_PADDING_SIZE); - if (!nal->rbsp_buffer) - return AVERROR(ENOMEM); - - dst = nal->rbsp_buffer; - - memcpy(dst, src, i); - si = di = i; - while (si + 2 < length) { - // remove escapes (very rare 1:2^22) - if (src[si + 2] > 3) { - dst[di++] = src[si++]; - dst[di++] = src[si++]; - } else if (src[si] == 0 && src[si + 1] == 0) { - if (src[si + 2] == 3) { // escape - dst[di++] = 0; - dst[di++] = 0; - si += 3; - - s->skipped_bytes++; - if (s->skipped_bytes_pos_size < s->skipped_bytes) { - s->skipped_bytes_pos_size *= 2; - av_reallocp_array(&s->skipped_bytes_pos, - s->skipped_bytes_pos_size, - sizeof(*s->skipped_bytes_pos)); - if (!s->skipped_bytes_pos) - return AVERROR(ENOMEM); - } - if (s->skipped_bytes_pos) - s->skipped_bytes_pos[s->skipped_bytes-1] = di - 1; - continue; - } else // next start code - goto nsc; - } - - dst[di++] = src[si++]; - } - while (si < length) - dst[di++] = src[si++]; - -nsc: - memset(dst + di, 0, FF_INPUT_BUFFER_PADDING_SIZE); - - nal->data = dst; - nal->size = di; - nal->raw_data = src; - nal->raw_size = si; - return si; -} - static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) { int i, consumed, ret = 0; @@ -2982,17 +2869,15 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) nal = &s->nals[s->nb_nals]; consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal); - - s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes; - s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size; - s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos; - - if (consumed < 0) { ret = consumed; goto fail; } + s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes; + s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size; + s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos; + ret = init_get_bits8(&s->HEVClc->gb, nal->data, nal->size); if (ret < 0) goto fail; diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 8ab9f84f6f..bd0c48bf81 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -944,9 +944,6 @@ int ff_hevc_decode_nal_sps(HEVCContext *s); int ff_hevc_decode_nal_pps(HEVCContext *s); int ff_hevc_decode_nal_sei(HEVCContext *s); -int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length, - HEVCNAL *nal); - /** * Mark all frames in DPB as unused for reference. */ @@ -1051,6 +1048,12 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size); +/** + * Extract the raw (unescaped) HEVC bitstream. + */ +int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length, + HEVCNAL *nal); + extern const uint8_t ff_hevc_qpel_extra_before[4]; extern const uint8_t ff_hevc_qpel_extra_after[4]; extern const uint8_t ff_hevc_qpel_extra[4]; diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c new file mode 100644 index 0000000000..260f1e1aa6 --- /dev/null +++ b/libavcodec/hevc_parse.c @@ -0,0 +1,145 @@ +/* + * HEVC common code + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <string.h> + +#include "config.h" + +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "hevc.h" + +/* FIXME: This is adapted from ff_h264_decode_nal, avoiding duplication + * between these functions would be nice. */ +int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length, + HEVCNAL *nal) +{ + int i, si, di; + uint8_t *dst; + + if (s) + s->skipped_bytes = 0; +#define STARTCODE_TEST \ + if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ + if (src[i + 2] != 3) { \ + /* startcode, so we must be past the end */ \ + length = i; \ + } \ + break; \ + } +#if HAVE_FAST_UNALIGNED +#define FIND_FIRST_ZERO \ + if (i > 0 && !src[i]) \ + i--; \ + while (src[i]) \ + i++ +#if HAVE_FAST_64BIT + for (i = 0; i + 1 < length; i += 9) { + if (!((~AV_RN64A(src + i) & + (AV_RN64A(src + i) - 0x0100010001000101ULL)) & + 0x8000800080008080ULL)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 7; + } +#else + for (i = 0; i + 1 < length; i += 5) { + if (!((~AV_RN32A(src + i) & + (AV_RN32A(src + i) - 0x01000101U)) & + 0x80008080U)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 3; + } +#endif /* HAVE_FAST_64BIT */ +#else + for (i = 0; i + 1 < length; i += 2) { + if (src[i]) + continue; + if (i > 0 && src[i - 1] == 0) + i--; + STARTCODE_TEST; + } +#endif /* HAVE_FAST_UNALIGNED */ + + if (i >= length - 1) { // no escaped 0 + nal->data = + nal->raw_data = src; + nal->size = + nal->raw_size = length; + return length; + } + + av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size, + length + FF_INPUT_BUFFER_PADDING_SIZE); + if (!nal->rbsp_buffer) + return AVERROR(ENOMEM); + + dst = nal->rbsp_buffer; + + memcpy(dst, src, i); + si = di = i; + while (si + 2 < length) { + // remove escapes (very rare 1:2^22) + if (src[si + 2] > 3) { + dst[di++] = src[si++]; + dst[di++] = src[si++]; + } else if (src[si] == 0 && src[si + 1] == 0) { + if (src[si + 2] == 3) { // escape + dst[di++] = 0; + dst[di++] = 0; + si += 3; + + if (s) { + s->skipped_bytes++; + if (s->skipped_bytes_pos_size < s->skipped_bytes) { + s->skipped_bytes_pos_size *= 2; + av_reallocp_array(&s->skipped_bytes_pos, + s->skipped_bytes_pos_size, + sizeof(*s->skipped_bytes_pos)); + if (!s->skipped_bytes_pos) + return AVERROR(ENOMEM); + } + if (s->skipped_bytes_pos) + s->skipped_bytes_pos[s->skipped_bytes-1] = di - 1; + } + continue; + } else // next start code + goto nsc; + } + + dst[di++] = src[si++]; + } + while (si < length) + dst[di++] = src[si++]; + +nsc: + memset(dst + di, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + nal->data = dst; + nal->size = di; + nal->raw_data = src; + nal->raw_size = si; + return si; +} + |