@ -43,6 +43,7 @@
# include "avformat.h"
# include "internal.h"
# include "mxf.h"
# include "config.h"
static const int NTSC_samples_per_frame [ ] = { 1602 , 1601 , 1602 , 1601 , 1602 , 0 } ;
static const int NTSC_60_samples_per_frame [ ] = { 801 , 801 , 801 , 801 , 800 , 0 } ;
@ -93,6 +94,7 @@ static const struct {
{ CODEC_ID_MPEG2VIDEO , 0 } ,
{ CODEC_ID_PCM_S24LE , 1 } ,
{ CODEC_ID_PCM_S16LE , 1 } ,
{ CODEC_ID_DVVIDEO , 15 } ,
{ CODEC_ID_NONE }
} ;
@ -169,6 +171,51 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x06 , 0x01 , 0x10 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x02 , 0x02 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 } ,
mxf_write_generic_sound_desc } ,
// DV Unknwon
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x7F , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x00 , 0x00 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV25 525/60
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x40 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x01 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV25 625/50
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x41 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV50 525/60
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x50 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x03 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV50 625/50
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x51 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x04 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV100 1080/60
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x60 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x05 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV100 1080/50
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x61 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x06 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV100 720/60
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x62 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x07 , 0x00 } ,
mxf_write_cdci_desc } ,
// DV100 720/50
{ { 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x02 , 0x02 , 0x63 , 0x01 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x01 , 0x02 , 0x01 , 0x01 , 0x0D , 0x01 , 0x03 , 0x01 , 0x18 , 0x01 , 0x01 , 0x00 } ,
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x04 , 0x01 , 0x02 , 0x02 , 0x02 , 0x02 , 0x08 , 0x00 } ,
mxf_write_cdci_desc } ,
{ { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ,
{ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ,
{ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ,
@ -830,9 +877,9 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
// video line map
switch ( st - > codec - > height ) {
case 576 : f1 = 23 ; f2 = 336 ; break ;
case 576 : f1 = 23 ; f2 = st - > codec - > codec_id = = CODEC_ID_DVVIDEO ? 335 : 336 ; break ;
case 608 : f1 = 7 ; f2 = 320 ; break ;
case 480 : f1 = 20 ; f2 = 283 ; break ;
case 480 : f1 = 20 ; f2 = st - > codec - > codec_id = = CODEC_ID_DVVIDEO ? 285 : 283 ; break ;
case 512 : f1 = 7 ; f2 = 270 ; break ;
case 720 : f1 = 26 ; f2 = 0 ; break ; // progressive
case 1080 : f1 = 21 ; f2 = 584 ; break ;
@ -1291,6 +1338,76 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
avio_flush ( pb ) ;
}
static int mxf_parse_dv_frame ( AVFormatContext * s , AVStream * st , AVPacket * pkt )
{
MXFContext * mxf = s - > priv_data ;
MXFStreamContext * sc = st - > priv_data ;
uint8_t * vs_pack , * vsc_pack ;
int i , ul_index , frame_size , stype , pal ;
if ( mxf - > header_written )
return 1 ;
// Check for minimal frame size
if ( pkt - > size < 120000 )
return - 1 ;
vs_pack = pkt - > data + 80 * 5 + 48 ;
vsc_pack = pkt - > data + 80 * 5 + 53 ;
stype = vs_pack [ 3 ] & 0x1f ;
pal = ( vs_pack [ 3 ] > > 5 ) & 0x1 ;
if ( ( vs_pack [ 2 ] & 0x07 ) = = 0x02 )
sc - > aspect_ratio = ( AVRational ) { 16 , 9 } ;
else
sc - > aspect_ratio = ( AVRational ) { 4 , 3 } ;
sc - > interlaced = ( vsc_pack [ 3 ] > > 4 ) & 0x01 ;
// TODO: fix dv encoder to set proper FF/FS value in VSC pack
// and set field dominance accordingly
// av_log(s, AV_LOG_DEBUG, "DV vsc pack ff/ss = %x\n", vsc_pack[2] >> 6);
switch ( stype ) {
case 0x18 : // DV100 720p
ul_index = 6 + pal ;
frame_size = pal ? 288000 : 240000 ;
if ( sc - > interlaced ) {
av_log ( s , AV_LOG_ERROR , " source marked as interlaced but codec profile is progressive " ) ;
sc - > interlaced = 0 ;
}
break ;
case 0x14 : // DV100 1080i
ul_index = 4 + pal ;
frame_size = pal ? 576000 : 480000 ;
break ;
case 0x04 : // DV50
ul_index = 2 + pal ;
frame_size = pal ? 288000 : 240000 ;
break ;
default : // DV25
ul_index = 0 + pal ;
frame_size = pal ? 144000 : 120000 ;
}
sc - > index = ul_index + 16 ;
sc - > codec_ul = & mxf_essence_container_uls [ sc - > index ] . codec_ul ;
mxf - > edit_unit_byte_count = KAG_SIZE ;
for ( i = 0 ; i < s - > nb_streams ; i + + ) {
AVStream * st = s - > streams [ i ] ;
MXFStreamContext * sc = st - > priv_data ;
if ( st - > codec - > codec_type = = AVMEDIA_TYPE_AUDIO ) {
mxf - > edit_unit_byte_count + = 16 + 4 + sc - > aic . samples [ 0 ] * sc - > aic . sample_size ;
mxf - > edit_unit_byte_count + = klv_fill_size ( mxf - > edit_unit_byte_count ) ;
} else if ( st - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
mxf - > edit_unit_byte_count + = 16 + 4 + frame_size ;
mxf - > edit_unit_byte_count + = klv_fill_size ( mxf - > edit_unit_byte_count ) ;
}
}
return 1 ;
}
static const UID mxf_mpeg2_codec_uls [ ] = {
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x03 , 0x04 , 0x01 , 0x02 , 0x02 , 0x01 , 0x01 , 0x10 , 0x00 } , // MP-ML I-Frame
{ 0x06 , 0x0E , 0x2B , 0x34 , 0x04 , 0x01 , 0x01 , 0x03 , 0x04 , 0x01 , 0x02 , 0x02 , 0x01 , 0x01 , 0x11 , 0x00 } , // MP-ML Long GOP
@ -1537,6 +1654,9 @@ static int mxf_write_header(AVFormatContext *s)
MXFStreamContext * sc = s - > streams [ i ] - > priv_data ;
// update element count
sc - > track_essence_element_key [ 13 ] = present [ sc - > index ] ;
if ( ! memcmp ( sc - > track_essence_element_key , mxf_essence_container_uls [ 15 ] . element_ul , 13 ) ) // DV
sc - > order = ( 0x15 < < 24 ) | AV_RB32 ( sc - > track_essence_element_key + 13 ) ;
else
sc - > order = AV_RB32 ( sc - > track_essence_element_key + 12 ) ;
}
@ -1691,6 +1811,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
av_log ( s , AV_LOG_ERROR , " could not get mpeg2 profile and level \n " ) ;
return - 1 ;
}
} else if ( st - > codec - > codec_id = = CODEC_ID_DVVIDEO ) {
if ( ! mxf_parse_dv_frame ( s , st , pkt ) ) {
av_log ( s , AV_LOG_ERROR , " could not get dv profile \n " ) ;
return - 1 ;
}
}
if ( ! mxf - > header_written ) {