diff options
Diffstat (limited to 'libavcodec/extract_extradata_bsf.c')
-rw-r--r-- | libavcodec/extract_extradata_bsf.c | 96 |
1 files changed, 67 insertions, 29 deletions
diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index 20b30803b8..ed6509c681 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -65,7 +65,7 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, int extradata_size = 0; const int *extradata_nal_types; int nb_extradata_nal_types; - int i, ret = 0; + int i, has_sps = 0, has_vps = 0, ret = 0; if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { extradata_nal_types = extradata_nal_types_hevc; @@ -76,30 +76,42 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, } ret = ff_h2645_packet_split(&h2645_pkt, pkt->data, pkt->size, - ctx, 0, 0, ctx->par_in->codec_id); + ctx, 0, 0, ctx->par_in->codec_id, 1); if (ret < 0) return ret; for (i = 0; i < h2645_pkt.nb_nals; i++) { H2645NAL *nal = &h2645_pkt.nals[i]; - if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) + if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) { extradata_size += nal->raw_size + 3; + if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) { + if (nal->type == HEVC_NAL_SPS) has_sps = 1; + if (nal->type == HEVC_NAL_VPS) has_vps = 1; + } else { + if (nal->type == H264_NAL_SPS) has_sps = 1; + } + } } - if (extradata_size) { + if (extradata_size && + ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) || + (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) { AVBufferRef *filtered_buf; uint8_t *extradata, *filtered_data; if (s->remove) { filtered_buf = av_buffer_alloc(pkt->size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!filtered_buf) + if (!filtered_buf) { + ret = AVERROR(ENOMEM); goto fail; + } filtered_data = filtered_buf->data; } extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!extradata) { av_buffer_unref(&filtered_buf); + ret = AVERROR(ENOMEM); goto fail; } @@ -137,19 +149,17 @@ static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size) { ExtractExtradataContext *s = ctx->priv_data; + const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size; uint32_t state = UINT32_MAX; int has_extradata = 0, extradata_size = 0; - int i; - for (i = 0; i < pkt->size; i++) { - state = (state << 8) | pkt->data[i]; - if (IS_MARKER(state)) { - if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) { - has_extradata = 1; - } else if (has_extradata) { - extradata_size = i - 3; - break; - } + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &state); + if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) { + has_extradata = 1; + } else if (has_extradata && IS_MARKER(state)) { + extradata_size = ptr - 4 - pkt->data; + break; } } @@ -170,19 +180,18 @@ static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, return 0; } -static int extract_extradata_mpeg124(AVBSFContext *ctx, AVPacket *pkt, +static int extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size) { ExtractExtradataContext *s = ctx->priv_data; - int is_mpeg12 = ctx->par_in->codec_id == AV_CODEC_ID_MPEG1VIDEO || - ctx->par_in->codec_id == AV_CODEC_ID_MPEG2VIDEO; uint32_t state = UINT32_MAX; - int i; + int i, found = 0; for (i = 0; i < pkt->size; i++) { state = (state << 8) | pkt->data[i]; - if ((is_mpeg12 && state != 0x1B3 && state != 0x1B5 && state < 0x200 && state >= 0x100) || - (!is_mpeg12 && (state == 0x1B3 || state == 0x1B6))) { + if (state == 0x1B3) + found = 1; + else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) { if (i > 3) { *size = i - 3; *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -202,17 +211,46 @@ static int extract_extradata_mpeg124(AVBSFContext *ctx, AVPacket *pkt, return 0; } +static int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt, + uint8_t **data, int *size) +{ + ExtractExtradataContext *s = ctx->priv_data; + const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size; + uint32_t state = UINT32_MAX; + + while (ptr < end) { + ptr = avpriv_find_start_code(ptr, end, &state); + if (state == 0x1B3 || state == 0x1B6) { + if (ptr - pkt->data > 4) { + *size = ptr - 4 - pkt->data; + *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!*data) + return AVERROR(ENOMEM); + + memcpy(*data, pkt->data, *size); + + if (s->remove) { + pkt->data += *size; + pkt->size -= *size; + } + } + break; + } + } + return 0; +} + static const struct { enum AVCodecID id; int (*extract)(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size); } extract_tab[] = { - { AV_CODEC_ID_CAVS, extract_extradata_mpeg124 }, + { AV_CODEC_ID_CAVS, extract_extradata_mpeg4 }, { AV_CODEC_ID_H264, extract_extradata_h2645 }, { AV_CODEC_ID_HEVC, extract_extradata_h2645 }, - { AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg124 }, - { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg124 }, - { AV_CODEC_ID_MPEG4, extract_extradata_mpeg124 }, + { AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg12 }, + { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12 }, + { AV_CODEC_ID_MPEG4, extract_extradata_mpeg4 }, { AV_CODEC_ID_VC1, extract_extradata_vc1 }, }; |