@ -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 * ipc = s - > priv_data ;
int next = END_NOT_FOUND ;
DNxUcParseContext * pc ;
pc = ( DNxUcParseContext * ) s - > priv_data ;
s - > pict_type = AV_PICTURE_TYPE_NONE ;
if ( ! buf_size ) {
return 0 ;
* 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 ;
}
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 " ) ;
* 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 ;
ipc - > pc . state64 = state ;
} else if ( ipc - > remaining < = buf_size ) {
next = ipc - > remaining ;
ipc - > remaining = 0 ;
} else {
ipc - > remaining - = buf_size ;
}
if ( pc - > nr_bytes > buf_size - HEADER_SIZE + icmp_offset ) {
av_log ( avctx , AV_LOG_ERROR , " Insufficient size of image essence data. \n " ) ;
if ( ff_combine_frame ( & ipc - > pc , next , & buf , & buf_size ) < 0 ) {
* poutbuf = NULL ;
* 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 = {