@ -206,6 +206,7 @@ typedef struct {
struct AVAES * aesc ;
uint8_t * local_tags ;
int local_tags_count ;
uint64_t last_partition ;
uint64_t footer_partition ;
KLVPacket current_klv_data ;
int current_klv_index ;
@ -245,6 +246,7 @@ static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x
static const uint8_t mxf_crypto_source_container_ul [ ] = { 0x06 , 0x0e , 0x2b , 0x34 , 0x01 , 0x01 , 0x01 , 0x09 , 0x06 , 0x01 , 0x01 , 0x02 , 0x02 , 0x00 , 0x00 , 0x00 } ;
static const uint8_t mxf_encrypted_triplet_key [ ] = { 0x06 , 0x0e , 0x2b , 0x34 , 0x02 , 0x04 , 0x01 , 0x07 , 0x0d , 0x01 , 0x03 , 0x01 , 0x02 , 0x7e , 0x01 , 0x00 } ;
static const uint8_t mxf_encrypted_essence_container [ ] = { 0x06 , 0x0e , 0x2b , 0x34 , 0x04 , 0x01 , 0x01 , 0x07 , 0x0d , 0x01 , 0x03 , 0x01 , 0x02 , 0x0b , 0x01 , 0x00 } ;
static const uint8_t mxf_random_index_pack_key [ ] = { 0x06 , 0x0E , 0x2B , 0x34 , 0x02 , 0x05 , 0x01 , 0x01 , 0x0D , 0x01 , 0x02 , 0x01 , 0x01 , 0x11 , 0x01 , 0x00 } ;
static const uint8_t mxf_sony_mpeg4_extradata [ ] = { 0x06 , 0x0e , 0x2b , 0x34 , 0x04 , 0x01 , 0x01 , 0x01 , 0x0e , 0x06 , 0x06 , 0x02 , 0x02 , 0x01 , 0x00 , 0x00 } ;
# define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y)))
@ -1850,25 +1852,30 @@ static int mxf_parse_handle_essence(MXFContext *mxf)
if ( mxf - > parsing_backward ) {
return mxf_seek_to_previous_partition ( mxf ) ;
} else {
if ( ! mxf - > footer_partition ) {
av_dlog ( mxf - > fc , " no footer \n " ) ;
uint64_t offset = mxf - > footer_partition ? mxf - > footer_partition
: mxf - > last_partition ;
if ( ! offset ) {
av_dlog ( mxf - > fc , " no last partition \n " ) ;
return 0 ;
}
av_dlog ( mxf - > fc , " seeking to footer \n " ) ;
av_dlog ( mxf - > fc , " seeking to last partition \n " ) ;
/* remember where we were so we don't end up seeking further back than this */
mxf - > last_forward_tell = avio_tell ( pb ) ;
if ( ! pb - > seekable ) {
av_log ( mxf - > fc , AV_LOG_INFO , " file is not seekable - not parsing footer \n " ) ;
av_log ( mxf - > fc , AV_LOG_INFO , " file is not seekable - not parsing last partition \n " ) ;
return - 1 ;
}
/* seek to footer partition and parse backward */
if ( ( ret = avio_seek ( pb , mxf - > run_in + mxf - > footer_partition , SEEK_SET ) ) < 0 ) {
av_log ( mxf - > fc , AV_LOG_ERROR , " failed to seek to footer @ 0x% " PRIx64 " (% " PRId64 " ) - partial file? \n " ,
mxf - > run_in + mxf - > footer_partition , ret ) ;
/* seek to last partition and parse backward */
if ( ( ret = avio_seek ( pb , mxf - > run_in + offset , SEEK_SET ) ) < 0 ) {
av_log ( mxf - > fc , AV_LOG_ERROR ,
" failed to seek to last partition @ 0x% " PRIx64
" (% " PRId64 " ) - partial file? \n " ,
mxf - > run_in + offset , ret ) ;
return ret ;
}
@ -1998,6 +2005,34 @@ static void mxf_handle_small_eubc(AVFormatContext *s)
mxf - > edit_units_per_packet = 1920 ;
}
static void mxf_read_random_index_pack ( AVFormatContext * s )
{
MXFContext * mxf = s - > priv_data ;
uint32_t length ;
int64_t file_size ;
KLVPacket klv ;
if ( ! s - > pb - > seekable )
return ;
file_size = avio_size ( s - > pb ) ;
avio_seek ( s - > pb , file_size - 4 , SEEK_SET ) ;
length = avio_rb32 ( s - > pb ) ;
if ( length < = 32 | | length > = FFMIN ( file_size , INT_MAX ) )
goto end ;
avio_seek ( s - > pb , file_size - length , SEEK_SET ) ;
if ( klv_read_packet ( & klv , s - > pb ) < 0 | |
! IS_KLV_KEY ( klv . key , mxf_random_index_pack_key ) | |
klv . length ! = length - 20 )
goto end ;
avio_skip ( s - > pb , klv . length - 12 ) ;
mxf - > last_partition = avio_rb64 ( s - > pb ) ;
end :
avio_seek ( s - > pb , mxf - > run_in , SEEK_SET ) ;
}
static int mxf_read_header ( AVFormatContext * s )
{
MXFContext * mxf = s - > priv_data ;
@ -2016,7 +2051,10 @@ static int mxf_read_header(AVFormatContext *s)
mxf - > fc = s ;
mxf - > run_in = avio_tell ( s - > pb ) ;
mxf_read_random_index_pack ( s ) ;
while ( ! s - > pb - > eof_reached ) {
const MXFMetadataReadTableEntry * metadata ;
if ( klv_read_packet ( & klv , s - > pb ) < 0 ) {