demux: mkv: handle WAVE_FORMAT_MPEG_ADTS_AAC
[vlc.git] / modules / access / dcp / dcp.cpp
blob970685ca9598f4a6c448796b1b32780b7ad2dacc
1 /*****************************************************************************
2 * Copyright (C) 2012-2013 VLC authors and VideoLAN
4 * Authors:
5 * Nicolas Bertrand <nico@isf.cc>
6 * Simona-Marinela Prodea <simona dot marinela dot prodea at gmail dot com>
7 * Jean-Baptiste Kempf <jb@videolan.org>
8 * Guillaume Gonnaud
9 * Valentin Vetter <vvetter@outlook.com>
10 * Anthony Giniers
11 * Ludovic Hoareau
12 * Loukmane Dessai
13 * Pierre Villard <pierre dot villard dot fr at gmail dot com>
14 * Claire Etienne
15 * Aurélie Sbinné
16 * Samuel Kerjose
17 * Julien Puyobro
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms of the GNU Lesser General Public License as published by
21 * the Free Software Foundation; either version 2.1 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public License
30 * along with this program; if not, write to the Free Software Foundation,
31 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
32 *****************************************************************************/
34 /**
35 * @file dcp.cpp
36 * @brief DCP access-demux module for Digital Cinema Packages using asdcp library
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
43 #define KDM_HELP_TEXT "KDM file"
44 #define KDM_HELP_LONG_TEXT "Path to Key Delivery Message XML file"
46 /* VLC core API headers */
47 #include <vlc_common.h>
48 #include <vlc_demux.h>
49 #include <vlc_plugin.h>
50 #include <vlc_xml.h>
51 #include <vlc_url.h>
52 #include <vlc_aout.h>
54 #ifdef _WIN32
55 # define KM_WIN32
56 #endif
58 /* ASDCP headers */
59 #include <AS_DCP.h>
61 #include <vector>
63 #include "dcpparser.h"
65 using namespace ASDCP;
67 #define FRAME_BUFFER_SIZE 1302083 /* maximum frame length, in bytes, after
68 "Digital Cinema System Specification Version 1.2
69 with Errata as of 30 August 2012" */
71 /* Forward declarations */
72 static int Open( vlc_object_t * );
73 static void Close( vlc_object_t * );
75 /* Module descriptor */
76 vlc_module_begin()
77 set_shortname( N_( "DCP" ) )
78 add_shortcut( "dcp" )
79 add_loadfile( "kdm", "", KDM_HELP_TEXT, KDM_HELP_LONG_TEXT, false )
80 set_description( N_( "Digital Cinema Package module" ) )
81 set_capability( "access_demux", 0 )
82 set_category( CAT_INPUT )
83 set_subcategory( SUBCAT_INPUT_ACCESS )
84 set_callbacks( Open, Close )
85 vlc_module_end()
87 //! Kind of MXF MEDIA TYPE
88 typedef enum MxfMedia_t {
89 MXF_UNKNOWN = 0,
90 MXF_PICTURE,
91 MXF_AUDIO,
92 } MxfMedia_t;
94 union videoReader_t
96 /* JPEG2000 essence type */
97 ASDCP::JP2K::MXFReader *p_PicMXFReader;
99 /* JPEG2000 stereoscopic essence type */
100 ASDCP::JP2K::MXFSReader *p_PicMXFSReader;
102 /* MPEG2 essence type */
103 ASDCP::MPEG2::MXFReader *p_VideoMXFReader;
106 struct audioReader_t
108 PCM::MXFReader *p_AudioMXFReader;
111 /* ASDCP library (version 1.10.48) can handle files having one of the following Essence Types, as defined in AS_DCP.h:
112 ESS_UNKNOWN, // the file is not a supported AS-DCP essence container
113 ESS_MPEG2_VES, // the file contains an MPEG video elementary stream
114 ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
115 ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
116 ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
117 ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources
118 ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic).
120 The classes for handling these essence types are defined in AS_DCP.h and are different for each essence type, respectively. The demux_sys_t structure contains members for handling each of these essence types.
123 class demux_sys_t
125 public:
126 /* ASDCP Picture Essence Type */
127 EssenceType_t PictureEssType;
129 /* ASDCP Video MXF Reader */
130 std::vector<videoReader_t> v_videoReader;
132 /* ASDCP Audio MXF Reader */
133 std::vector<audioReader_t> v_audioReader;
135 /* audio buffer size */
136 uint32_t i_audio_buffer;
138 /* elementary streams */
139 es_out_id_t *p_video_es;
140 es_out_id_t *p_audio_es;
142 /* DCP object */
143 dcp_t *p_dcp;
145 /* current absolute frame number */
146 uint32_t frame_no;
148 /* frame rate */
149 int frame_rate_num;
150 int frame_rate_denom;
152 /* total number of frames */
153 uint32_t frames_total;
155 /* current video reel */
156 unsigned int i_video_reel;
158 /* current audio reel */
159 unsigned int i_audio_reel;
161 uint8_t i_chans_to_reorder; /* do we need channel reordering */
162 uint8_t pi_chan_table[AOUT_CHAN_MAX];
163 uint8_t i_channels;
165 mtime_t i_pts;
167 demux_sys_t():
168 PictureEssType ( ESS_UNKNOWN ),
169 v_videoReader(),
170 v_audioReader(),
171 p_video_es( NULL ),
172 p_audio_es( NULL ),
173 p_dcp( NULL ),
174 frame_no( 0 ),
175 frames_total( 0 ),
176 i_video_reel( 0 ),
177 i_audio_reel( 0 ) {};
179 ~demux_sys_t()
181 switch ( PictureEssType )
183 case ESS_UNKNOWN:
184 break;
185 case ESS_JPEG_2000:
186 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
188 delete v_videoReader[i].p_PicMXFReader;
190 break;
191 case ESS_JPEG_2000_S:
192 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
194 delete v_videoReader[i].p_PicMXFSReader;
196 break;
197 case ESS_MPEG2_VES:
198 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
200 delete v_videoReader[i].p_VideoMXFReader;
202 break;
203 default:
204 break;
207 for ( unsigned int i = 0; i < v_audioReader.size(); i++ )
209 delete v_audioReader[i].p_AudioMXFReader;
212 delete p_dcp;
216 /*TODO: basic correlation between SMPTE S428-3/S429-2
217 * Real sound is more complex with case of left/right surround, ...
218 * and hearing impaired/Narration channels */
220 /* 1 channel: mono */
221 static const uint32_t i_channels_1[] =
222 { AOUT_CHAN_LEFT, 0 };
224 /* 2 channels: stereo */
225 static const uint32_t i_channels_2[]=
226 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 };
228 /* 4 channels */
229 static const uint32_t i_channels_4[] =
230 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
231 AOUT_CHAN_LFE, 0 };
233 /* 6 channels: 5.1 */
234 static const uint32_t i_channels_6[] =
235 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
236 AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
237 0 };
239 /* 7 channels: 6.1 */
240 static const uint32_t i_channels_7[] =
241 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
242 AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
243 AOUT_CHAN_REARCENTER, 0 };
245 /* 8 channels: 7.1 */
246 static const uint32_t i_channels_8[] =
247 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
248 AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
249 AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0 };
251 /* 9 channels; 8.1 */
252 static const uint32_t i_channels_9[] =
253 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
254 AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
255 AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_REARCENTER, 0 };
257 static const uint32_t *pi_channels_aout [] =
258 { NULL,
259 i_channels_1,
260 i_channels_2,
261 NULL,
262 i_channels_4,
263 NULL,
264 i_channels_6,
265 i_channels_7,
266 i_channels_8,
267 i_channels_9 };
269 static const unsigned i_channel_mask[] =
270 { 0,
271 AOUT_CHAN_LEFT,
272 AOUT_CHANS_STEREO,
274 AOUT_CHANS_3_1,
276 AOUT_CHANS_5_1,
277 AOUT_CHANS_6_1_MIDDLE,
278 AOUT_CHANS_7_1,
279 AOUT_CHANS_8_1 };
281 /*****************************************************************************
282 * Local prototypes
283 *****************************************************************************/
285 static int Demux( demux_t * );
286 static int Control( demux_t *, int, va_list );
288 int dcpInit ( demux_t *p_demux );
289 int parseXML ( demux_t * p_demux );
290 static inline void fillVideoFmt(
291 video_format_t * fmt, unsigned int width, unsigned int height,
292 unsigned int frame_rate_num, unsigned int frame_rate_denom );
293 void CloseDcpAndMxf( demux_t *p_demux );
297 /*****************************************************************************
298 * Open: module init function
299 *****************************************************************************/
300 static int Open( vlc_object_t *obj )
302 demux_t *p_demux = ( demux_t* ) obj;
303 demux_sys_t *p_sys;
304 es_format_t video_format, audio_format;
305 int retval;
307 if( !p_demux->psz_file )
308 return VLC_EGENERIC;
310 p_sys = new ( nothrow ) demux_sys_t();
311 if( unlikely( p_sys == NULL ) ) {
312 return VLC_ENOMEM;
314 p_demux->p_sys = p_sys;
316 /* Allocate DCP object */
317 dcp_t *p_dcp = new ( nothrow ) dcp_t;
318 if( unlikely( p_dcp == NULL ) ) {
319 delete p_sys;
320 return VLC_ENOMEM;
322 p_sys->p_dcp = p_dcp;
325 /* handle the DCP directory, saving the paths for audio and video file, returning error if unsuccessful */
326 if( ( retval = dcpInit( p_demux ) ) )
327 goto error;
329 /* Open video file */
330 EssenceType_t essInter;
331 for ( size_t i = 0; i < ( p_sys->p_dcp->video_reels.size() ); i++ )
333 EssenceType( p_sys->p_dcp->video_reels[i].filename.c_str(), essInter );
334 if ( i == 0 )
336 p_sys->PictureEssType = essInter;
338 else
340 if ( essInter != p_sys->PictureEssType )
342 msg_Err( p_demux, "Integrity check failed : different essence containers" );
343 retval = VLC_EGENERIC;
344 goto error;
348 switch( essInter )
350 case ESS_UNKNOWN:
351 msg_Err( p_demux, "The file %s is not a supported AS_DCP essence container", p_sys->p_dcp->video_reels[i].filename.c_str() );
352 retval = VLC_EGENERIC;
353 goto error;
355 case ESS_JPEG_2000:
356 case ESS_JPEG_2000_S: {
357 JP2K::PictureDescriptor PicDesc;
358 if (p_sys->PictureEssType == ESS_JPEG_2000_S) { /* 3D JPEG2000 */
359 JP2K::MXFSReader * p_PicMXFSReader = new ( nothrow ) JP2K::MXFSReader();
361 if( !p_PicMXFSReader) {
362 retval = VLC_ENOMEM;
363 goto error;
365 if( !ASDCP_SUCCESS( p_PicMXFSReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
366 msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->video_reels[i].filename.c_str() );
367 retval = VLC_EGENERIC;
368 delete p_PicMXFSReader;
369 goto error;
372 p_PicMXFSReader->FillPictureDescriptor( PicDesc );
373 videoReader_t videoReader;
374 videoReader.p_PicMXFSReader = p_PicMXFSReader;
375 p_sys->v_videoReader.push_back(videoReader);
376 } else { /* 2D JPEG2000 */
377 JP2K::MXFReader *p_PicMXFReader = new ( nothrow ) JP2K::MXFReader();
378 if( !p_PicMXFReader ) {
379 retval = VLC_ENOMEM;
380 goto error;
382 if( !ASDCP_SUCCESS( p_PicMXFReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
383 msg_Err( p_demux, "File %s could not be opened with ASDCP",
384 p_sys->p_dcp->video_reels[i].filename.c_str() );
385 retval = VLC_EGENERIC;
386 delete p_PicMXFReader;
387 goto error;
390 p_PicMXFReader->FillPictureDescriptor( PicDesc );
391 videoReader_t videoReader;
392 videoReader.p_PicMXFReader = p_PicMXFReader;
393 p_sys->v_videoReader.push_back(videoReader);
395 es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_JPEG2000 );
396 fillVideoFmt( &video_format.video, PicDesc.StoredWidth, PicDesc.StoredHeight,
397 PicDesc.EditRate.Numerator, PicDesc.EditRate.Denominator );
400 if ( i > 0 ) {
401 if ( p_sys->frame_rate_num != PicDesc.EditRate.Numerator ||
402 p_sys->frame_rate_denom != PicDesc.EditRate.Denominator )
404 msg_Err( p_demux, "Integrity check failed : different frame rates" );
405 retval = VLC_EGENERIC;
406 goto error;
409 else
411 p_sys->frame_rate_num = PicDesc.EditRate.Numerator;
412 p_sys->frame_rate_denom = PicDesc.EditRate.Denominator;
415 p_sys->frames_total += p_sys->p_dcp->video_reels[i].i_duration;
416 break;
418 case ESS_MPEG2_VES: {
420 MPEG2::MXFReader *p_VideoMXFReader = new ( nothrow ) MPEG2::MXFReader();
422 videoReader_t videoReader;
423 videoReader.p_VideoMXFReader = p_VideoMXFReader;
424 p_sys->v_videoReader.push_back(videoReader);
426 MPEG2::VideoDescriptor VideoDesc;
428 if( !p_VideoMXFReader ) {
429 retval = VLC_ENOMEM;
430 goto error;
433 if( !ASDCP_SUCCESS( p_VideoMXFReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
434 msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->video_reels[i].filename.c_str() );
435 retval = VLC_EGENERIC;
436 goto error;
439 p_VideoMXFReader->FillVideoDescriptor( VideoDesc );
441 es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_MPGV );
442 fillVideoFmt( &video_format.video, VideoDesc.StoredWidth, VideoDesc.StoredHeight,
443 VideoDesc.EditRate.Numerator, VideoDesc.EditRate.Denominator );
446 if ( i > 0 ) {
447 if ( p_sys->frame_rate_num != VideoDesc.EditRate.Numerator ||
448 p_sys->frame_rate_denom != VideoDesc.EditRate.Denominator)
450 msg_Err( p_demux, "Integrity check failed : different frame rates" );
451 retval = VLC_EGENERIC;
452 goto error;
455 else
457 p_sys->frame_rate_num = VideoDesc.EditRate.Numerator;
458 p_sys->frame_rate_denom = VideoDesc.EditRate.Denominator;
461 p_sys->frames_total += p_sys->p_dcp->video_reels[i].i_duration;
462 break;
464 default:
465 msg_Err( p_demux, "Unrecognized video format" );
466 retval = VLC_EGENERIC;
467 goto error;
471 if ( (p_sys->frame_rate_num == 0) || (p_sys->frame_rate_denom == 0) ) {
472 msg_Err(p_demux, "Invalid frame rate (%i/%i)",
473 p_sys->frame_rate_num, p_sys->frame_rate_denom);
474 retval = VLC_EGENERIC;
475 goto error;
478 if( ( p_sys->p_video_es = es_out_Add( p_demux->out, &video_format ) ) == NULL ) {
479 msg_Err( p_demux, "Failed to add video es" );
480 retval = VLC_EGENERIC;
481 goto error;
484 /* Open audio file */
485 EssenceType_t AudioEssType;
486 EssenceType_t AudioEssTypeCompare;
488 if( !p_sys->p_dcp->audio_reels.empty() )
490 EssenceType( p_sys->p_dcp->audio_reels[0].filename.c_str(), AudioEssType );
492 if ( (AudioEssType == ESS_PCM_24b_48k) || (AudioEssType == ESS_PCM_24b_96k) ) {
493 PCM::AudioDescriptor AudioDesc;
495 for ( size_t i = 0; i < ( p_sys->p_dcp->audio_reels.size() ); i++)
497 if ( i != 0 )
499 EssenceType( p_sys->p_dcp->audio_reels[i].filename.c_str(), AudioEssTypeCompare );
500 if ( AudioEssTypeCompare != AudioEssType )
502 msg_Err( p_demux, "Integrity check failed : different audio essence types in %s",
503 p_sys->p_dcp->audio_reels[i].filename.c_str() );
504 retval = VLC_EGENERIC;
505 goto error;
508 PCM::MXFReader *p_AudioMXFReader = new ( nothrow ) PCM::MXFReader();
510 if( !p_AudioMXFReader ) {
511 retval = VLC_ENOMEM;
512 goto error;
515 if( !ASDCP_SUCCESS( p_AudioMXFReader->OpenRead( p_sys->p_dcp->audio_reels[i].filename.c_str() ) ) ) {
516 msg_Err( p_demux, "File %s could not be opened with ASDCP",
517 p_sys->p_dcp->audio_reels[i].filename.c_str() );
518 retval = VLC_EGENERIC;
519 delete p_AudioMXFReader;
520 goto error;
523 p_AudioMXFReader->FillAudioDescriptor( AudioDesc );
525 if ( (AudioDesc.ChannelCount >= sizeof(pi_channels_aout)/sizeof(uint32_t *))
526 || (pi_channels_aout[AudioDesc.ChannelCount] == NULL) )
528 msg_Err(p_demux, " DCP module does not support %i channels", AudioDesc.ChannelCount);
529 retval = VLC_EGENERIC;
530 delete p_AudioMXFReader;
531 goto error;
533 audioReader_t audioReader;
534 audioReader.p_AudioMXFReader = p_AudioMXFReader;
535 p_sys->v_audioReader.push_back( audioReader );
538 es_format_Init( &audio_format, AUDIO_ES, VLC_CODEC_S24L );
539 if( AudioDesc.AudioSamplingRate.Denominator != 0 )
540 audio_format.audio.i_rate =
541 AudioDesc.AudioSamplingRate.Numerator
542 / AudioDesc.AudioSamplingRate.Denominator;
543 else if ( AudioEssType == ESS_PCM_24b_96k )
544 audio_format.audio.i_rate = 96000;
545 else
546 audio_format.audio.i_rate = 48000;
548 p_sys->i_audio_buffer = PCM::CalcFrameBufferSize( AudioDesc );
549 if (p_sys->i_audio_buffer == 0) {
550 msg_Err( p_demux, "Failed to get audio buffer size" );
551 retval = VLC_EGENERIC;
552 goto error;
555 audio_format.audio.i_bitspersample = AudioDesc.QuantizationBits;
556 audio_format.audio.i_blockalign = AudioDesc.BlockAlign;
557 audio_format.audio.i_channels =
558 p_sys->i_channels = AudioDesc.ChannelCount;
560 /* Manage channel orders */
561 p_sys->i_chans_to_reorder = aout_CheckChannelReorder(
562 pi_channels_aout[AudioDesc.ChannelCount], NULL,
563 i_channel_mask[AudioDesc.ChannelCount], p_sys->pi_chan_table );
565 if( ( p_sys->p_audio_es = es_out_Add( p_demux->out, &audio_format ) ) == NULL ) {
566 msg_Err( p_demux, "Failed to add audio es" );
567 retval = VLC_EGENERIC;
568 goto error;
570 } else {
571 msg_Err( p_demux, "The file %s is not a supported AS_DCP essence container",
572 p_sys->p_dcp->audio_reels[0].filename.c_str() );
573 retval = VLC_EGENERIC;
574 goto error;
577 p_demux->pf_demux = Demux;
578 p_demux->pf_control = Control;
579 p_sys->frame_no = p_sys->p_dcp->video_reels[0].i_entrypoint;
581 return VLC_SUCCESS;
582 error:
583 CloseDcpAndMxf( p_demux );
584 return retval;
588 /*****************************************************************************
589 * Close: module destroy function
590 *****************************************************************************/
591 static inline void Close( vlc_object_t *obj )
593 demux_t *p_demux = ( demux_t* ) obj;
594 CloseDcpAndMxf( p_demux );
599 /*****************************************************************************
600 * Demux: DCP Demuxing function
601 *****************************************************************************/
602 static int Demux( demux_t *p_demux )
604 demux_sys_t *p_sys = p_demux->p_sys;
605 block_t *p_video_frame = NULL, *p_audio_frame = NULL;
607 PCM::FrameBuffer AudioFrameBuff( p_sys->i_audio_buffer);
608 AESDecContext video_aes_ctx, audio_aes_ctx;
610 /* swaping video reels */
611 if ( p_sys->frame_no == p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_absolute_end )
613 if ( p_sys->i_video_reel + 1 == p_sys->v_videoReader.size() )
615 return 0;
617 else
619 p_sys->i_video_reel++;
623 /* swaping audio reels */
624 if ( !p_sys->p_dcp->audio_reels.empty() && p_sys->frame_no == p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].i_absolute_end )
626 if ( p_sys->i_audio_reel + 1 == p_sys->v_audioReader.size() )
628 return 0;//should never go there
630 else
632 p_sys->i_audio_reel++;
636 /* video frame */
638 /* initialize AES context, if reel is encrypted */
639 if( p_sys &&
640 p_sys->p_dcp &&
641 p_sys->p_dcp->video_reels.size() > p_sys->i_video_reel &&
642 p_sys->p_dcp->video_reels[p_sys->i_video_reel].p_key )
644 if( ! ASDCP_SUCCESS( video_aes_ctx.InitKey( p_sys->p_dcp->video_reels[p_sys->i_video_reel].p_key->getKey() ) ) )
646 msg_Err( p_demux, "ASDCP failed to initialize AES key" );
647 goto error;
651 switch( p_sys->PictureEssType )
653 case ESS_JPEG_2000:
654 case ESS_JPEG_2000_S:{
655 JP2K::FrameBuffer PicFrameBuff(FRAME_BUFFER_SIZE);
656 int nextFrame = p_sys->frame_no + p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_correction;
657 if ( ( p_video_frame = block_Alloc( FRAME_BUFFER_SIZE )) == NULL )
658 goto error;
660 if ( ! ASDCP_SUCCESS(
661 PicFrameBuff.SetData(p_video_frame->p_buffer, FRAME_BUFFER_SIZE)) )
662 goto error_asdcp;
663 if ( p_sys->PictureEssType == ESS_JPEG_2000_S ) {
664 if ( ! ASDCP_SUCCESS(
665 p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFSReader->ReadFrame(nextFrame, JP2K::SP_LEFT, PicFrameBuff, &video_aes_ctx, 0)) ) {
666 PicFrameBuff.SetData(0,0);
667 goto error_asdcp;
669 } else {
670 if ( ! ASDCP_SUCCESS(
671 p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFReader->ReadFrame(nextFrame, PicFrameBuff, &video_aes_ctx, 0)) ) {
672 PicFrameBuff.SetData(0,0);
673 goto error_asdcp;
676 p_video_frame->i_buffer = PicFrameBuff.Size();
677 break;
679 case ESS_MPEG2_VES: {
680 MPEG2::FrameBuffer VideoFrameBuff(FRAME_BUFFER_SIZE);
681 if ( ( p_video_frame = block_Alloc( FRAME_BUFFER_SIZE )) == NULL )
682 goto error;
684 if ( ! ASDCP_SUCCESS(
685 VideoFrameBuff.SetData(p_video_frame->p_buffer, FRAME_BUFFER_SIZE)) )
686 goto error_asdcp;
688 if ( ! ASDCP_SUCCESS(
689 p_sys->v_videoReader[p_sys->i_video_reel].p_VideoMXFReader->ReadFrame(p_sys->frame_no + p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_correction, VideoFrameBuff, &video_aes_ctx, 0)) ) {
690 VideoFrameBuff.SetData(0,0);
691 goto error_asdcp;
694 p_video_frame->i_buffer = VideoFrameBuff.Size();
695 break;
697 default:
698 msg_Err( p_demux, "Unrecognized video format" );
699 goto error;
702 p_video_frame->i_length = CLOCK_FREQ * p_sys->frame_rate_denom / p_sys->frame_rate_num;
703 p_video_frame->i_pts = CLOCK_FREQ * p_sys->frame_no * p_sys->frame_rate_denom / p_sys->frame_rate_num;
705 if( !p_sys->p_dcp->audio_reels.empty() )
707 /* audio frame */
708 if ( ( p_audio_frame = block_Alloc( p_sys->i_audio_buffer )) == NULL ) {
709 goto error;
712 /* initialize AES context, if reel is encrypted */
713 if( p_sys &&
714 p_sys->p_dcp &&
715 p_sys->p_dcp->audio_reels.size() > p_sys->i_audio_reel &&
716 p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key )
718 if( ! ASDCP_SUCCESS( audio_aes_ctx.InitKey( p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key->getKey() ) ) )
720 msg_Err( p_demux, "ASDCP failed to initialize AES key" );
721 goto error;
725 if ( ! ASDCP_SUCCESS(
726 AudioFrameBuff.SetData(p_audio_frame->p_buffer, p_sys->i_audio_buffer)) ) {
727 goto error_asdcp;
730 if ( ! ASDCP_SUCCESS(
731 p_sys->v_audioReader[p_sys->i_audio_reel].p_AudioMXFReader->ReadFrame(p_sys->frame_no + p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].i_correction, AudioFrameBuff, &audio_aes_ctx, 0)) ) {
732 AudioFrameBuff.SetData(0,0);
733 goto error_asdcp;
736 if( p_sys->i_chans_to_reorder )
737 aout_ChannelReorder( p_audio_frame->p_buffer, p_audio_frame->i_buffer,
738 p_sys->i_channels,
739 p_sys->pi_chan_table, VLC_CODEC_S24L );
741 p_audio_frame->i_buffer = AudioFrameBuff.Size();
742 p_audio_frame->i_length = CLOCK_FREQ * p_sys->frame_rate_denom / p_sys->frame_rate_num;
743 p_audio_frame->i_pts = CLOCK_FREQ * p_sys->frame_no * p_sys->frame_rate_denom / p_sys->frame_rate_num;
744 /* Video is the main pts */
745 if ( p_audio_frame->i_pts != p_video_frame->i_pts ) {
746 msg_Err( p_demux, "Audio and video frame pts are not in sync" );
750 p_sys->i_pts = p_video_frame->i_pts;
751 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pts );
752 if(p_video_frame)
753 es_out_Send( p_demux->out, p_sys->p_video_es, p_video_frame );
754 if(p_audio_frame)
755 es_out_Send( p_demux->out, p_sys->p_audio_es, p_audio_frame );
757 p_sys->frame_no++;
759 return 1;
761 error_asdcp:
762 msg_Err( p_demux, "Couldn't read frame with ASDCP");
763 error:
764 if (p_video_frame)
765 block_Release(p_video_frame);
766 if (p_audio_frame)
767 block_Release(p_audio_frame);
768 return -1;
771 /*****************************************************************************
772 * Control: handle the controls
773 *****************************************************************************/
774 static int Control( demux_t *p_demux, int query, va_list args )
776 double f,*pf;
777 bool *pb;
778 int64_t *pi64, i64;
779 demux_sys_t *p_sys = p_demux->p_sys;
781 switch ( query )
783 case DEMUX_CAN_PAUSE:
784 case DEMUX_CAN_CONTROL_PACE:
785 pb = va_arg ( args, bool* );
786 *pb = true;
787 break;
789 case DEMUX_CAN_SEEK:
790 pb = va_arg( args, bool * );
791 if( p_sys->PictureEssType != ESS_MPEG2_VES )
792 *pb = true;
793 else
794 *pb = false;
795 break;
797 case DEMUX_SET_PAUSE_STATE:
798 return VLC_SUCCESS;
800 case DEMUX_GET_POSITION:
801 pf = va_arg( args, double * );
802 if( p_sys->frames_total != 0 )
803 *pf = (double) p_sys->frame_no / (double) p_sys->frames_total;
804 else {
805 msg_Warn( p_demux, "Total number of frames is 0" );
806 *pf = 0.0;
808 break;
810 case DEMUX_SET_POSITION:
811 f = va_arg( args, double );
812 p_sys->frame_no = (int) ( f * p_sys->frames_total );
813 break;
815 case DEMUX_GET_LENGTH:
816 pi64 = va_arg ( args, int64_t * );
817 *pi64 = ( p_sys->frames_total * p_sys->frame_rate_denom / p_sys->frame_rate_num ) * CLOCK_FREQ;
818 break;
820 case DEMUX_GET_TIME:
821 pi64 = va_arg( args, int64_t * );
822 *pi64 = p_sys->i_pts >= 0 ? p_sys->i_pts : 0;
823 break;
825 case DEMUX_SET_TIME:
826 i64 = va_arg( args, int64_t );
827 msg_Warn( p_demux, "DEMUX_SET_TIME" );
828 p_sys->frame_no = i64 * p_sys->frame_rate_num / ( CLOCK_FREQ * p_sys->frame_rate_denom );
829 p_sys->i_pts= i64;
830 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pts);
831 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, ( mtime_t ) i64 );
832 break;
833 case DEMUX_GET_PTS_DELAY:
834 pi64 = va_arg( args, int64_t * );
835 *pi64 =
836 INT64_C(1000) * var_InheritInteger( p_demux, "file-caching" );
837 return VLC_SUCCESS;
840 default:
841 msg_Warn( p_demux, "Unknown query %d in DCP Control", query );
842 return VLC_EGENERIC;
845 return VLC_SUCCESS;
849 /*****************************************************************************
850 * Low-level functions : string manipulation, free function, etc
851 *****************************************************************************/
853 * Function to fill video_format_t fields for an elementary stream
854 * @param fmt video format structure
855 * @param width picture width
856 * @param height picture height
857 * @param frame_rate_num video frame rate numerator
858 * @param frame_rate_denom video frame rate denominator
860 static inline void fillVideoFmt( video_format_t * fmt, unsigned int width, unsigned int height, unsigned int frame_rate_num, unsigned int frame_rate_denom )
862 fmt->i_width = width;
863 fmt->i_height = height;
864 /* As input are square pixels let VLC or decoder fix SAR, origin,
865 * and visible area */
866 fmt->i_frame_rate = frame_rate_num;
867 fmt->i_frame_rate_base = frame_rate_denom;
871 * Function to free memory in case of error or when closing the module
872 * @param p_demux DCP access-demux
876 void CloseDcpAndMxf( demux_t *p_demux )
878 demux_sys_t *p_sys = p_demux->p_sys;
879 /* close the files */
880 switch( p_sys->PictureEssType )
882 case ESS_UNKNOWN:
883 break;
884 case ESS_JPEG_2000:
885 for ( size_t i = 0; i < p_sys->v_videoReader.size(); i++ )
887 if( p_sys->v_videoReader[i].p_PicMXFReader )
888 p_sys->v_videoReader[i].p_PicMXFReader->Close();
890 break;
891 case ESS_JPEG_2000_S:
892 for ( size_t i = 0; i < p_sys->v_videoReader.size(); i++ )
894 if( p_sys->v_videoReader[i].p_PicMXFSReader )
895 p_sys->v_videoReader[i].p_PicMXFSReader->Close();
897 break;
898 case ESS_MPEG2_VES:
899 for ( size_t i = 0; i < p_sys->v_videoReader.size(); i++ )
901 if( p_sys->v_videoReader[i].p_VideoMXFReader )
902 p_sys->v_videoReader[i].p_VideoMXFReader->Close();
904 break;
905 default:
906 break;
909 for ( size_t i = 0; i < p_sys->v_audioReader.size(); i++ )
911 if( p_sys->v_audioReader[i].p_AudioMXFReader )
912 p_sys->v_audioReader[i].p_AudioMXFReader->Close();
915 delete( p_demux->p_sys );
919 /*****************************************************************************
920 * DCP init
921 *****************************************************************************/
924 * Function to handle the operations with the DCP directory.
925 * @param p_demux Demux pointer.
926 * @return Integer according to the success or not of the process.
928 int dcpInit ( demux_t *p_demux )
930 int retval;
932 demux_sys_t *p_sys = p_demux->p_sys;
933 dcp_t *p_dcp = p_sys->p_dcp;
935 p_dcp->path = p_demux->psz_file;
936 /* Add a '/' in end of path if needed */
937 if ( *(p_dcp->path).rbegin() != '/')
938 p_dcp->path.append( "/" );
940 /* Parsing XML files to get audio and video files */
941 msg_Dbg( p_demux, "parsing XML files..." );
942 if( ( retval = parseXML( p_demux ) ) )
943 return retval;
945 msg_Dbg(p_demux, "parsing XML files done");
947 return VLC_SUCCESS;
951 /*****************************************************************************
952 * functions for XML parsing
953 *****************************************************************************/
956 * Function to retrieve the path to the ASSETMAP file.
957 * @param p_demux DCP access_demux.
959 static std::string assetmapPath( demux_t * p_demux )
961 DIR *dir = NULL;
962 struct dirent *ent = NULL;
963 dcp_t *p_dcp = p_demux->p_sys->p_dcp;
964 std::string result;
966 if( ( dir = opendir (p_dcp->path.c_str() ) ) != NULL )
968 /* print all the files and directories within directory */
969 while( ( ent = readdir ( dir ) ) != NULL )
971 if( strcasecmp( "assetmap", ent->d_name ) == 0 || strcasecmp( "assetmap.xml", ent->d_name ) == 0 )
973 /* copy of "path" in "res" */
974 result = p_dcp->path;
975 result.append( ent->d_name );
976 break;
979 closedir( dir );
981 else
982 msg_Err( p_demux, "Could not open the directory: %s", p_dcp->path.c_str() );
984 /* if no assetmap file */
985 if( result.empty() )
986 msg_Err( p_demux, "No ASSETMAP found in the directory: %s", p_dcp->path.c_str() );
988 return result;
993 * Function which parses XML files in DCP directory in order to get video and audio files
994 * @param p_demux Demux pointer.
995 * @return Integer according to the success or not of the operation
997 int parseXML ( demux_t * p_demux )
999 int retval;
1001 std::string assetmap_path = assetmapPath( p_demux );
1002 /* We get the ASSETMAP file path */
1003 if( assetmap_path.empty() )
1004 return VLC_EGENERIC;
1006 /* We parse the ASSETMAP File in order to get CPL File path, PKL File path
1007 and to store UID/Path of all files in DCP directory (except ASSETMAP file) */
1008 AssetMap *assetmap = new (nothrow) AssetMap( p_demux, assetmap_path, p_demux->p_sys->p_dcp );
1009 if( ( retval = assetmap->Parse() ) )
1010 return retval;
1012 delete assetmap;
1013 return VLC_SUCCESS; /* TODO : perform checking on XML parsing */