The current parser does things which a parser should not, like skipping parts of the packet header, but it does not actually able to packetize a raw DNXUC bitstream.
Rework the parser logic to work similar to other parsers and be able to correctly packetize raw DNXUC bitstreams. Signed-off-by: Marton Balint <c...@passwd.hu> --- libavcodec/dnxuc_parser.c | 122 ++++++++++++++------------------------ 1 file changed, 44 insertions(+), 78 deletions(-) diff --git a/libavcodec/dnxuc_parser.c b/libavcodec/dnxuc_parser.c index 12472c7a2d..14f19efe67 100644 --- a/libavcodec/dnxuc_parser.c +++ b/libavcodec/dnxuc_parser.c @@ -20,99 +20,65 @@ */ /* - This parser for DNxUncompressed video data is mostly based on - reverse engineering of output generated by DaVinci Resolve 19 - but was later also checked against the SMPTE RDD 50 specification. - - Limitations: Multiple image planes are not supported. -*/ + * This parser for DNxUncompressed video data is mostly based on the public + * SMPTE RDD 50:2019 specification. + */ -#include "avcodec.h" -#include "libavutil/intreadwrite.h" +#include "parser.h" +#include "libavutil/bswap.h" typedef struct DNxUcParseContext { - uint32_t fourcc_tag; - uint32_t width; - uint32_t height; - uint32_t nr_bytes; + ParseContext pc; + uint32_t remaining; } DNxUcParseContext; -/* -DNxUncompressed frame data comes wrapped in nested boxes of metadata -(box structure: len + fourcc marker + data): - -[0-4] len of outer essence unit box (typically 37 bytes of header + frame data) -[4-7] fourcc 'pack' - -[8-11] len of "signal info box" (always 21) -[12-15] fourcc 'sinf' -[16-19] frame width / line packing size -[20-23] frame hight / nr of lines -[24-27] fourcc pixel format indicator -[28] frame_layout (0: progressive, 1: interlaced) - -[29-32] len of "signal data box" (nr of frame data bytes + 8) -[33-36] fourcc 'sdat' -[37-..] frame data - -A sequence of 'signal info'+'signal data' box pairs wrapped in -'icmp'(=image component) boxes can be utilized to compose more -complex multi plane images. -This feature is only partially supported in the present implementation. -We never pick more than the first pair of info and image data enclosed -in this way. -*/ - static int dnxuc_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { - const int HEADER_SIZE = 37; - int icmp_offset = 0; - - DNxUcParseContext *pc; - pc = (DNxUcParseContext *) s->priv_data; - - if (!buf_size) { - return 0; - } - if (buf_size > 16 && MKTAG('i','c','m','p') == AV_RL32(buf+12)){ - icmp_offset += 8; - } - if ( buf_size < 37 + icmp_offset /* check metadata structure expectations */ - || MKTAG('p','a','c','k') != AV_RL32(buf+4+icmp_offset) - || MKTAG('s','i','n','f') != AV_RL32(buf+12+icmp_offset) - || MKTAG('s','d','a','t') != AV_RL32(buf+33+icmp_offset)){ - av_log(avctx, AV_LOG_ERROR, "can't read DNxUncompressed metadata.\n"); + DNxUcParseContext *ipc = s->priv_data; + int next = END_NOT_FOUND; + + s->pict_type = AV_PICTURE_TYPE_NONE; + + *poutbuf_size = 0; + *poutbuf = NULL; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + if (ipc->remaining == 0) { + uint64_t state = ipc->pc.state64; + for (int i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (ipc->pc.index + i >= 7 && (uint32_t)state == MKBETAG('p','a','c','k')) { + uint32_t size = av_bswap32(state >> 32); + if (size >= 8) { + next = i - 7; + ipc->remaining = size + FFMIN(next, 0); + break; + } + } + } + ipc->pc.state64 = state; + } else if (ipc->remaining <= buf_size) { + next = ipc->remaining; + ipc->remaining = 0; + } else { + ipc->remaining -= buf_size; + } + if (ff_combine_frame(&ipc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; *poutbuf_size = 0; return buf_size; + } } - pc->fourcc_tag = AV_RL32(buf+24+icmp_offset); - pc->width = AV_RL32(buf+16+icmp_offset); - pc->height = AV_RL32(buf+20+icmp_offset); - pc->nr_bytes = AV_RL32(buf+29+icmp_offset) - 8; - - if (!avctx->codec_tag) { - av_log(avctx, AV_LOG_INFO, "dnxuc_parser: '%s' %dx%d %dbpp %d\n", - av_fourcc2str(pc->fourcc_tag), - pc->width, pc->height, - (pc->nr_bytes*8)/(pc->width*pc->height), - pc->nr_bytes); - avctx->codec_tag = pc->fourcc_tag; - } - - if (pc->nr_bytes > buf_size - HEADER_SIZE + icmp_offset){ - av_log(avctx, AV_LOG_ERROR, "Insufficient size of image essence data.\n"); - *poutbuf_size = 0; - return buf_size; - } - - *poutbuf = buf + HEADER_SIZE + icmp_offset; - *poutbuf_size = pc->nr_bytes; + *poutbuf = buf; + *poutbuf_size = buf_size; - return buf_size; + return next; } const AVCodecParser ff_dnxuc_parser = { -- 2.43.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".