/*****************************************************************************
* drms_decrypt: unscramble a chunk of data
*****************************************************************************/
-void drms_decrypt( void *_p_drms, uint32_t *p_buffer, uint32_t i_bytes )
+void drms_decrypt( void *_p_drms, uint32_t *p_buffer, uint32_t i_bytes, uint32_t *p_key )
{
struct drms_s *p_drms = (struct drms_s *)_p_drms;
- uint32_t p_key[ 4 ];
+ uint32_t p_key_buf[ 4 ];
unsigned int i_blocks;
/* AES is a block cypher, round down the byte count */
i_bytes = i_blocks * 16;
/* Initialise the key */
- memcpy( p_key, p_drms->p_key, 16 );
+ if( !p_key )
+ {
+ p_key = p_key_buf;
+ memcpy( p_key, p_drms->p_key, 16 );
+ }
/* Unscramble */
while( i_blocks-- )
}
}
+/*****************************************************************************
+ * drms_get_p_key: copy the p_key into user buffer
+ ****************************************************************************/
+void drms_get_p_key( void *_p_drms, uint32_t *p_key )
+{
+ struct drms_s *p_drms = (struct drms_s *)_p_drms;
+
+ memcpy( p_key, p_drms->p_key, 16 );
+}
+
/*****************************************************************************
* drms_init: initialise a DRMS structure
*****************************************************************************
memcpy( p_priv, p_info, 64 );
memcpy( p_drms->p_key, md5.p_digest, 16 );
- drms_decrypt( p_drms, p_priv, 64 );
+ drms_decrypt( p_drms, p_priv, 64, NULL );
REVERSE( p_priv, 64 );
if( p_priv[ 0 ] != 0x6e757469 ) /* itun */
void *drms_alloc( const char *psz_homedir ){ return 0; }
void drms_free( void *a ){}
-void drms_decrypt( void *a, uint32_t *b, uint32_t c ){}
+void drms_decrypt( void *a, uint32_t *b, uint32_t c, uint32_t *k ){}
+void drms_get_p_key( void *p_drms, uint32_t *p_key );
int drms_init( void *a, uint32_t b, uint8_t *c, uint32_t d ){ return -1; }
#endif /* defined( UNDER_CE ) */
extern int drms_init( void *p_drms, uint32_t i_type,
uint8_t *p_info, uint32_t i_len );
extern void drms_decrypt( void *p_drms, uint32_t *p_buffer,
- uint32_t i_len );
+ uint32_t i_len, uint32_t *p_key );
+extern void drms_get_p_key( void *p_drms, uint32_t *p_key );
#endif
MP4_GET2BYTES( p_box->data.p_sample_vide->i_qt_color_table );
stream_Seek( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 78);
+
+ if( p_box->i_type == FOURCC_drmi )
+ {
+ p_box->data.p_sample_vide->p_drms =
+ drms_alloc( config_GetHomeDir() );
+
+ if( p_box->data.p_sample_vide->p_drms == NULL )
+ {
+ msg_Err( p_stream, "drms_alloc() failed" );
+ }
+ }
+
MP4_ReadBoxContainerRaw( p_stream, p_box );
#ifdef MP4_VERBOSE
void MP4_FreeBox_sample_vide( MP4_Box_t *p_box )
{
FREENULL( p_box->data.p_sample_vide->p_qt_image_description );
+
+ if( p_box->i_type == FOURCC_drmi )
+ {
+ if( p_box->data.p_sample_vide->p_drms )
+ {
+ drms_free( p_box->data.p_sample_vide->p_drms );
+ }
+ }
}
static int MP4_ReadBox_sample_mp4s( stream_t *p_stream, MP4_Box_t *p_box )
MP4_READBOX_EXIT( 1 );
}
+static int MP4_ReadBox_frma( stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_frma_t );
+
+ MP4_GETFOURCC( p_box->data.p_frma->i_type );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream, "read box: \"frma\" i_type:%4.4s",
+ (char *)&p_box->data.p_frma->i_type );
+#endif
+
+ MP4_READBOX_EXIT( 1 );
+}
+
+static int MP4_ReadBox_skcr( stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_READBOX_ENTER( MP4_Box_data_frma_t );
+
+ MP4_GET4BYTES( p_box->data.p_skcr->i_init );
+ MP4_GET4BYTES( p_box->data.p_skcr->i_encr );
+ MP4_GET4BYTES( p_box->data.p_skcr->i_decr );
+
+#ifdef MP4_VERBOSE
+ msg_Dbg( p_stream, "read box: \"skcr\" i_init:%d i_encr:%d i_decr:%d",
+ p_box->data.p_skcr->i_init,
+ p_box->data.p_skcr->i_encr,
+ p_box->data.p_skcr->i_decr );
+#endif
+
+ MP4_READBOX_EXIT( 1 );
+}
+
static int MP4_ReadBox_drms( stream_t *p_stream, MP4_Box_t *p_box )
{
MP4_Box_t *p_drms_box = p_box;
+ void *p_drms = NULL;
MP4_READBOX_ENTER( uint8_t );
do
{
p_drms_box = p_drms_box->p_father;
- } while( p_drms_box && p_drms_box->i_type != FOURCC_drms );
+ } while( p_drms_box && p_drms_box->i_type != FOURCC_drms
+ && p_drms_box->i_type != FOURCC_drmi );
- if( p_drms_box && p_drms_box->data.p_sample_soun->p_drms )
+ if( p_drms_box && p_drms_box->i_type == FOURCC_drms )
+ p_drms = p_drms_box->data.p_sample_soun->p_drms;
+ else if( p_drms_box && p_drms_box->i_type == FOURCC_drmi )
+ p_drms = p_drms_box->data.p_sample_vide->p_drms;
+
+ if( p_drms_box && p_drms )
{
- int i_ret = drms_init( p_drms_box->data.p_sample_soun->p_drms,
- p_box->i_type, p_peek, i_read );
+ int i_ret = drms_init( p_drms, p_box->i_type, p_peek, i_read );
if( i_ret )
{
const char *psz_error;
msg_Err( p_stream, "drms_init(c%3.3s) failed (%s)",
(char *)&p_box->i_type+1, psz_error );
- drms_free( p_drms_box->data.p_sample_soun->p_drms );
- p_drms_box->data.p_sample_soun->p_drms = NULL;
+ drms_free( p_drms );
+
+ if( p_drms_box->i_type == FOURCC_drms )
+ p_drms_box->data.p_sample_soun->p_drms = NULL;
+ else if( p_drms_box->i_type == FOURCC_drmi )
+ p_drms_box->data.p_sample_vide->p_drms = NULL;
}
}
{ FOURCC_OggS, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
{ FOURCC_alac, MP4_ReadBox_sample_soun, MP4_FreeBox_sample_soun },
+ { FOURCC_drmi, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_vide, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_mp4v, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_SVQ1, MP4_ReadBox_sample_vide, MP4_FreeBox_sample_vide },
{ FOURCC_iviv, MP4_ReadBox_drms, MP4_FreeBox_Common },
{ FOURCC_name, MP4_ReadBox_drms, MP4_FreeBox_Common },
{ FOURCC_priv, MP4_ReadBox_drms, MP4_FreeBox_Common },
+ { FOURCC_frma, MP4_ReadBox_frma, MP4_FreeBox_Common },
+ { FOURCC_skcr, MP4_ReadBox_skcr, MP4_FreeBox_Common },
/* found in udta */
{ FOURCC_0xa9nam,MP4_ReadBox_0xa9xxx, MP4_FreeBox_0xa9xxx },
#define FOURCC_iviv VLC_FOURCC( 'i', 'v', 'i', 'v' )
#define FOURCC_name VLC_FOURCC( 'n', 'a', 'm', 'e' )
#define FOURCC_priv VLC_FOURCC( 'p', 'r', 'i', 'v' )
+#define FOURCC_drmi VLC_FOURCC( 'd', 'r', 'm', 'i' )
+#define FOURCC_frma VLC_FOURCC( 'f', 'r', 'm', 'a' )
+#define FOURCC_skcr VLC_FOURCC( 's', 'k', 'c', 'r' )
#define FOURCC_text VLC_FOURCC( 't', 'e', 'x', 't' )
#define FOURCC_tx3g VLC_FOURCC( 't', 'x', '3', 'g' )
int i_qt_image_description;
uint8_t *p_qt_image_description;
+ void *p_drms;
+
} MP4_Box_data_sample_vide_t;
#define MP4_TEXT_DISPLAY_FLAG_DONT_DISPLAY (1<<0)
} MP4_Box_data_cmov_t;
+typedef struct
+{
+ uint32_t i_type;
+} MP4_Box_data_frma_t;
+
+typedef struct
+{
+ uint32_t i_init;
+ uint32_t i_encr;
+ uint32_t i_decr;
+} MP4_Box_data_skcr_t;
+
typedef struct
{
uint8_t i_version;
MP4_Box_data_moviehintinformation_rtp_t p_moviehintinformation_rtp;
+ MP4_Box_data_frma_t *p_frma;
+ MP4_Box_data_skcr_t *p_skcr;
+
MP4_Box_data_rdrf_t *p_rdrf;
MP4_Box_data_rmdr_t *p_rmdr;
MP4_Box_data_rmqu_t *p_rmqu;
bool b_drms;
void *p_drms;
+ MP4_Box_t *p_skcr;
} mp4_track_t;
if( tk->b_drms && tk->p_drms )
{
- drms_decrypt( tk->p_drms, (uint32_t*)p_block->p_buffer,
- p_block->i_buffer );
+ if( tk->p_skcr )
+ {
+ uint32_t p_key[4];
+ drms_get_p_key( tk->p_drms, p_key );
+
+ for( int i_pos = tk->p_skcr->data.p_skcr->i_init; i_pos < p_block->i_buffer; )
+ {
+ int n = __MIN( tk->p_skcr->data.p_skcr->i_encr, p_block->i_buffer - i_pos );
+ drms_decrypt( tk->p_drms, (uint32_t*)&p_block->p_buffer[i_pos], n, p_key );
+ i_pos += n;
+ i_pos += __MIN( tk->p_skcr->data.p_skcr->i_decr, p_block->i_buffer - i_pos );
+ }
+ }
+ else
+ {
+ drms_decrypt( tk->p_drms, (uint32_t*)p_block->p_buffer,
+ p_block->i_buffer, NULL );
+ }
}
else if( tk->fmt.i_cat == SPU_ES )
{
MP4_Box_t *p_sample;
MP4_Box_t *p_esds;
MP4_Box_t *p_box;
+ MP4_Box_t *p_frma;
if( pp_es )
*pp_es = NULL;
p_track->p_sample = p_sample;
+ if( ( p_frma = MP4_BoxGet( p_track->p_sample, "sinf/frma" ) ) )
+ {
+ msg_Warn( p_demux, "Original Format Box: %4.4s", (char *)&p_frma->data.p_frma->i_type );
+
+ p_sample->i_type = p_frma->data.p_frma->i_type;
+ }
+
if( p_track->fmt.i_cat == AUDIO_ES && ( p_track->i_sample_size == 1 || p_track->i_sample_size == 2 ) )
{
MP4_Box_data_sample_soun_t *p_soun;
p_track->p_drms = p_track->b_drms ?
p_drms->data.p_sample_soun->p_drms : NULL;
+ if ( !p_drms )
+ {
+ p_drms = MP4_BoxGet( p_track->p_stsd, "drmi" );
+ p_track->b_drms = p_drms != NULL;
+ p_track->p_drms = p_track->b_drms ?
+ p_drms->data.p_sample_vide->p_drms : NULL;
+ }
+
+ if( p_drms )
+ p_track->p_skcr = MP4_BoxGet( p_drms, "sinf/skcr" );
+
/* Set language */
if( *language && strcmp( language, "```" ) && strcmp( language, "und" ) )
{