h2645_parse.c (libav-12) | : | h2645_parse.c (libav-12.1) | ||
---|---|---|---|---|
skipping to change at line 29 | skipping to change at line 29 | |||
*/ | */ | |||
#include <string.h> | #include <string.h> | |||
#include "config.h" | #include "config.h" | |||
#include "libavutil/intmath.h" | #include "libavutil/intmath.h" | |||
#include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | |||
#include "libavutil/mem.h" | #include "libavutil/mem.h" | |||
#include "bytestream.h" | ||||
#include "h2645_parse.h" | #include "h2645_parse.h" | |||
int ff_h2645_extract_rbsp(const uint8_t *src, int length, | int ff_h2645_extract_rbsp(const uint8_t *src, int length, | |||
H2645NAL *nal) | H2645NAL *nal) | |||
{ | { | |||
int i, si, di; | int i, si, di; | |||
uint8_t *dst; | uint8_t *dst; | |||
#define STARTCODE_TEST \ | #define STARTCODE_TEST \ | |||
if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ | if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ | |||
skipping to change at line 217 | skipping to change at line 218 | |||
break; | break; | |||
i++; | i++; | |||
} | } | |||
return i + 3; | return i + 3; | |||
} | } | |||
int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, | int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, | |||
void *logctx, int is_nalff, int nal_length_size, | void *logctx, int is_nalff, int nal_length_size, | |||
enum AVCodecID codec_id) | enum AVCodecID codec_id) | |||
{ | { | |||
GetByteContext bc; | ||||
int consumed, ret = 0; | int consumed, ret = 0; | |||
const uint8_t *next_avc = buf + (is_nalff ? 0 : length); | size_t next_avc = is_nalff ? 0 : length; | |||
bytestream2_init(&bc, buf, length); | ||||
pkt->nb_nals = 0; | pkt->nb_nals = 0; | |||
while (length >= 4) { | while (bytestream2_get_bytes_left(&bc) >= 4) { | |||
H2645NAL *nal; | H2645NAL *nal; | |||
int extract_length = 0; | int extract_length = 0; | |||
int skip_trailing_zeros = 1; | int skip_trailing_zeros = 1; | |||
/* | /* | |||
* Only parse an AVC1 length field if one is expected at the current | * Only parse an AVC1 length field if one is expected at the current | |||
* buffer position. There are unfortunately streams with multiple | * buffer position. There are unfortunately streams with multiple | |||
* NAL units covered by the length field. Those NAL units are delimited | * NAL units covered by the length field. Those NAL units are delimited | |||
* by Annex B start code prefixes. ff_h2645_extract_rbsp() detects it | * by Annex B start code prefixes. ff_h2645_extract_rbsp() detects it | |||
* correctly and consumes only the first NAL unit. The additional NAL | * correctly and consumes only the first NAL unit. The additional NAL | |||
* units are handled here in the Annex B parsing code. | * units are handled here in the Annex B parsing code. | |||
*/ | */ | |||
if (buf == next_avc) { | if (bytestream2_tell(&bc) == next_avc) { | |||
int i; | int i; | |||
for (i = 0; i < nal_length_size; i++) | for (i = 0; i < nal_length_size; i++) | |||
extract_length = (extract_length << 8) | buf[i]; | extract_length = (extract_length << 8) | bytestream2_get_byte(&b c); | |||
if (extract_length > length) { | if (extract_length > bytestream2_get_bytes_left(&bc)) { | |||
av_log(logctx, AV_LOG_ERROR, | av_log(logctx, AV_LOG_ERROR, | |||
"Invalid NAL unit size (%d > %d).\n", | "Invalid NAL unit size (%d > %d).\n", | |||
extract_length, length); | extract_length, bytestream2_get_bytes_left(&bc)); | |||
return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | |||
} | } | |||
buf += nal_length_size; | ||||
length -= nal_length_size; | ||||
// keep track of the next AVC1 length field | // keep track of the next AVC1 length field | |||
next_avc = buf + extract_length; | next_avc = bytestream2_tell(&bc) + extract_length; | |||
} else { | } else { | |||
/* | /* | |||
* expected to return immediately except for streams with mixed | * expected to return immediately except for streams with mixed | |||
* NAL unit coding | * NAL unit coding | |||
*/ | */ | |||
int buf_index = find_next_start_code(buf, next_avc); | int buf_index = find_next_start_code(bc.buffer, buf + next_avc); | |||
buf += buf_index; | bytestream2_skip(&bc, buf_index); | |||
length -= buf_index; | ||||
/* | /* | |||
* break if an AVC1 length field is expected at the current buffer | * break if an AVC1 length field is expected at the current buffer | |||
* position | * position | |||
*/ | */ | |||
if (buf == next_avc) | if (bytestream2_tell(&bc) == next_avc) | |||
continue; | continue; | |||
if (length > 0) { | if (bytestream2_get_bytes_left(&bc) > 0) { | |||
extract_length = length; | extract_length = bytestream2_get_bytes_left(&bc); | |||
} else if (pkt->nb_nals == 0) { | } else if (pkt->nb_nals == 0) { | |||
av_log(logctx, AV_LOG_ERROR, "No NAL unit found\n"); | av_log(logctx, AV_LOG_ERROR, "No NAL unit found\n"); | |||
return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | |||
} else { | } else { | |||
break; | break; | |||
} | } | |||
} | } | |||
if (pkt->nals_allocated < pkt->nb_nals + 1) { | if (pkt->nals_allocated < pkt->nb_nals + 1) { | |||
int new_size = pkt->nals_allocated + 1; | int new_size = pkt->nals_allocated + 1; | |||
skipping to change at line 289 | skipping to change at line 290 | |||
if (!tmp) | if (!tmp) | |||
return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | |||
pkt->nals = tmp; | pkt->nals = tmp; | |||
memset(pkt->nals + pkt->nals_allocated, 0, | memset(pkt->nals + pkt->nals_allocated, 0, | |||
(new_size - pkt->nals_allocated) * sizeof(*tmp)); | (new_size - pkt->nals_allocated) * sizeof(*tmp)); | |||
pkt->nals_allocated = new_size; | 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); | consumed = ff_h2645_extract_rbsp(bc.buffer, extract_length, nal); | |||
if (consumed < 0) | if (consumed < 0) | |||
return consumed; | return consumed; | |||
bytestream2_skip(&bc, consumed); | ||||
/* see commit 3566042a0 */ | /* see commit 3566042a0 */ | |||
if (consumed < length - 3 && | if (bytestream2_get_bytes_left(&bc) >= 4 && | |||
buf[consumed] == 0x00 && buf[consumed + 1] == 0x00 && | bytestream2_peek_be32(&bc) == 0x000001E0) | |||
buf[consumed + 2] == 0x01 && buf[consumed + 3] == 0xE0) | ||||
skip_trailing_zeros = 0; | skip_trailing_zeros = 0; | |||
nal->size_bits = get_bit_length(nal, skip_trailing_zeros); | nal->size_bits = get_bit_length(nal, skip_trailing_zeros); | |||
ret = init_get_bits(&nal->gb, nal->data, nal->size_bits); | ret = init_get_bits(&nal->gb, nal->data, nal->size_bits); | |||
if (ret < 0) | if (ret < 0) | |||
return ret; | return ret; | |||
if (codec_id == AV_CODEC_ID_HEVC) | if (codec_id == AV_CODEC_ID_HEVC) | |||
ret = hevc_parse_nal_header(nal, logctx); | ret = hevc_parse_nal_header(nal, logctx); | |||
else | else | |||
ret = h264_parse_nal_header(nal, logctx); | ret = h264_parse_nal_header(nal, logctx); | |||
if (ret <= 0) { | if (ret <= 0) { | |||
if (ret < 0) { | if (ret < 0) { | |||
av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", | av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", | |||
nal->type); | nal->type); | |||
} | } | |||
pkt->nb_nals--; | pkt->nb_nals--; | |||
} | } | |||
buf += consumed; | ||||
length -= consumed; | ||||
} | } | |||
return 0; | return 0; | |||
} | } | |||
void ff_h2645_packet_uninit(H2645Packet *pkt) | void ff_h2645_packet_uninit(H2645Packet *pkt) | |||
{ | { | |||
int i; | int i; | |||
for (i = 0; i < pkt->nals_allocated; i++) | for (i = 0; i < pkt->nals_allocated; i++) | |||
av_freep(&pkt->nals[i].rbsp_buffer); | av_freep(&pkt->nals[i].rbsp_buffer); | |||
End of changes. 18 change blocks. | ||||
22 lines changed or deleted | 21 lines changed or added |