Update to meson 0.54.2
[vlc.git] / modules / access / dcp / dcp.cpp
1 /*****************************************************************************
2  * Copyright (C) 2012-2013 VLC authors and VideoLAN
3  *
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
18  *
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.
23  *
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.
28  *
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  *****************************************************************************/
33
34 /**
35  * @file dcp.cpp
36  * @brief DCP access-demux module for Digital Cinema Packages using asdcp library
37  */
38
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
42
43 #define KDM_HELP_TEXT          N_("KDM file")
44 #define KDM_HELP_LONG_TEXT     N_("Path to Key Delivery Message XML file")
45
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>
53
54 #ifdef _WIN32
55 # define KM_WIN32
56 #endif
57
58 /* ASDCP headers */
59 #include <AS_DCP.h>
60
61 #include <vector>
62
63 #include "dcpparser.h"
64
65 using namespace ASDCP;
66
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" */
70
71 /* Forward declarations */
72 static int Open( vlc_object_t * );
73 static void Close( vlc_object_t * );
74
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)
80     set_description( N_( "Digital Cinema Package module" ) )
81     set_capability( "access", 0 )
82     set_category( CAT_INPUT )
83     set_subcategory( SUBCAT_INPUT_ACCESS )
84     set_callbacks( Open, Close )
85 vlc_module_end()
86
87 namespace {
88
89 //! Kind of MXF MEDIA TYPE
90 typedef enum MxfMedia_t {
91     MXF_UNKNOWN = 0,
92     MXF_PICTURE,
93     MXF_AUDIO,
94 } MxfMedia_t;
95
96 union videoReader_t
97 {
98    /* JPEG2000 essence type */
99    ASDCP::JP2K::MXFReader *p_PicMXFReader;
100
101    /* JPEG2000 stereoscopic essence type */
102    ASDCP::JP2K::MXFSReader *p_PicMXFSReader;
103
104    /* MPEG2 essence type */
105    ASDCP::MPEG2::MXFReader *p_VideoMXFReader;
106 };
107
108 struct audioReader_t
109 {
110     PCM::MXFReader *p_AudioMXFReader;
111 };
112
113 /* ASDCP library (version 1.10.48) can handle files having one of the following Essence Types, as defined in AS_DCP.h:
114     ESS_UNKNOWN,     // the file is not a supported AS-DCP essence container
115     ESS_MPEG2_VES,   // the file contains an MPEG video elementary stream
116     ESS_JPEG_2000,   // the file contains one or more JPEG 2000 codestreams
117     ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
118     ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
119     ESS_TIMED_TEXT,  // the file contains an XML timed text document and one or more resources
120     ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic).
121
122     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 */
124
125 class demux_sys_t
126 {
127  public:
128     /* ASDCP Picture Essence Type */
129     EssenceType_t PictureEssType;
130
131     /* ASDCP Video MXF Reader */
132     std::vector<videoReader_t> v_videoReader;
133
134     /* ASDCP Audio MXF Reader */
135     std::vector<audioReader_t> v_audioReader;
136
137     /* audio buffer size */
138     uint32_t i_audio_buffer;
139
140     /* elementary streams */
141     es_out_id_t *p_video_es;
142     es_out_id_t *p_audio_es;
143
144     /* DCP object */
145     dcp_t *p_dcp;
146
147     /* current absolute frame number */
148     uint32_t frame_no;
149
150     /* frame rate */
151     int frame_rate_num;
152     int frame_rate_denom;
153
154     /* total number of frames */
155     uint32_t frames_total;
156
157     /* current video reel */
158     unsigned int i_video_reel;
159
160     /* current audio reel */
161     unsigned int i_audio_reel;
162
163     uint8_t i_chans_to_reorder;            /* do we need channel reordering */
164     uint8_t pi_chan_table[AOUT_CHAN_MAX];
165     uint8_t i_channels;
166
167     vlc_tick_t i_pts;
168
169     demux_sys_t():
170         PictureEssType ( ESS_UNKNOWN ),
171         v_videoReader(),
172         v_audioReader(),
173         p_video_es( NULL ),
174         p_audio_es( NULL ),
175         p_dcp( NULL ),
176         frame_no( 0 ),
177         frames_total( 0 ),
178         i_video_reel( 0 ),
179         i_audio_reel( 0 ),
180         i_pts( 0 )
181     {}
182
183     ~demux_sys_t()
184     {
185         switch ( PictureEssType )
186         {
187             case ESS_UNKNOWN:
188                 break;
189             case ESS_JPEG_2000:
190                 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
191                 {
192                     delete v_videoReader[i].p_PicMXFReader;
193                 }
194                 break;
195             case ESS_JPEG_2000_S:
196                 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
197                 {
198                     delete v_videoReader[i].p_PicMXFSReader;
199                 }
200                 break;
201             case ESS_MPEG2_VES:
202                 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
203                 {
204                     delete v_videoReader[i].p_VideoMXFReader;
205                 }
206                 break;
207             default:
208                 break;
209         }
210
211         for ( unsigned int i = 0; i < v_audioReader.size(); i++ )
212         {
213             delete v_audioReader[i].p_AudioMXFReader;
214         }
215
216         delete p_dcp;
217     }
218 };
219
220 } // namespace
221
222 /*TODO: basic correlation between SMPTE S428-3/S429-2
223  * Real sound is more complex with case of left/right surround, ...
224  * and hearing impaired/Narration channels */
225
226 /* 1 channel: mono */
227 static const uint32_t i_channels_1[] =
228 { AOUT_CHAN_LEFT, 0 };
229
230 /* 2 channels: stereo */
231 static const uint32_t i_channels_2[]=
232 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 };
233
234 /* 4 channels */
235 static const uint32_t i_channels_4[] =
236 {   AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
237     AOUT_CHAN_LFE, 0  };
238
239 /* 6 channels: 5.1 */
240 static const uint32_t i_channels_6[] =
241 {   AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,      AOUT_CHAN_CENTER,
242     AOUT_CHAN_LFE,  AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,
243     0 };
244
245 /* 7 channels: 6.1 */
246 static const uint32_t i_channels_7[] =
247 {   AOUT_CHAN_LEFT,       AOUT_CHAN_RIGHT,    AOUT_CHAN_CENTER,
248     AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
249     AOUT_CHAN_REARCENTER, 0  };
250
251 /* 8 channels:  7.1 */
252 static const uint32_t i_channels_8[] =
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, 0 };
256
257 /* 9 channels; 8.1 */
258 static const uint32_t i_channels_9[] =
259 {   AOUT_CHAN_LEFT,        AOUT_CHAN_RIGHT,      AOUT_CHAN_CENTER,
260     AOUT_CHAN_LFE,         AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,
261     AOUT_CHAN_MIDDLELEFT,  AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_REARCENTER, 0 };
262
263 static const uint32_t *pi_channels_aout [] =
264 {   NULL,
265     i_channels_1,
266     i_channels_2,
267     NULL,
268     i_channels_4,
269     NULL,
270     i_channels_6,
271     i_channels_7,
272     i_channels_8,
273     i_channels_9 };
274
275 static const unsigned i_channel_mask[] =
276 {    0,
277     AOUT_CHAN_LEFT,
278     AOUT_CHANS_STEREO,
279     0,
280     AOUT_CHANS_3_1,
281     0,
282     AOUT_CHANS_5_1,
283     AOUT_CHANS_6_1_MIDDLE,
284     AOUT_CHANS_7_1,
285     AOUT_CHANS_8_1 };
286
287 /*****************************************************************************
288  * Local prototypes
289  *****************************************************************************/
290
291 static int Demux( demux_t * );
292 static int Control( demux_t *, int, va_list );
293
294 int dcpInit ( demux_t *p_demux );
295 int parseXML ( demux_t * p_demux );
296 static inline void fillVideoFmt(
297         video_format_t * fmt, unsigned int width, unsigned int height,
298         unsigned int frame_rate_num, unsigned int frame_rate_denom );
299 void CloseDcpAndMxf( demux_t *p_demux );
300
301
302
303 /*****************************************************************************
304  * Open: module init function
305  *****************************************************************************/
306 static int Open( vlc_object_t *obj )
307 {
308     demux_t *p_demux = ( demux_t* ) obj;
309     demux_sys_t *p_sys;
310     es_format_t video_format, audio_format;
311     int retval;
312
313     if( p_demux->out == NULL || p_demux->psz_filepath == NULL )
314         return VLC_EGENERIC;
315
316     p_sys = new ( nothrow ) demux_sys_t();
317     if( unlikely( p_sys == NULL ) ) {
318         return VLC_ENOMEM;
319     }
320     p_demux->p_sys = p_sys;
321
322     /* Allocate DCP object */
323     dcp_t *p_dcp = new ( nothrow ) dcp_t;
324     if( unlikely( p_dcp == NULL ) ) {
325         delete  p_sys;
326         return VLC_ENOMEM;
327     }
328     p_sys->p_dcp = p_dcp;
329
330
331     /* handle the DCP directory, saving the paths for audio and video file, returning error if unsuccessful */
332     if( ( retval = dcpInit( p_demux ) ) )
333         goto error;
334
335     /* Open video file */
336     EssenceType_t essInter;
337     for ( size_t i = 0; i < ( p_sys->p_dcp->video_reels.size() ); i++ )
338     {
339         EssenceType( p_sys->p_dcp->video_reels[i].filename.c_str(), essInter );
340         if ( i == 0 )
341         {
342             p_sys->PictureEssType = essInter;
343         }
344         else
345         {
346             if ( essInter != p_sys->PictureEssType )
347             {
348                 msg_Err( p_demux, "Integrity check failed : different essence containers" );
349                 retval = VLC_EGENERIC;
350                 goto error;
351             }
352         }
353
354         switch( essInter )
355         {
356             case ESS_UNKNOWN:
357                 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() );
358                 retval = VLC_EGENERIC;
359                 goto error;
360
361             case ESS_JPEG_2000:
362             case ESS_JPEG_2000_S: {
363                 JP2K::PictureDescriptor PicDesc;
364                 if (p_sys->PictureEssType == ESS_JPEG_2000_S) {     /* 3D JPEG2000 */
365                     JP2K::MXFSReader * p_PicMXFSReader = new ( nothrow ) JP2K::MXFSReader();
366
367                     if( !p_PicMXFSReader) {
368                         retval = VLC_ENOMEM;
369                         goto error;
370                     }
371                     if( !ASDCP_SUCCESS( p_PicMXFSReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
372                         msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->video_reels[i].filename.c_str() );
373                         retval = VLC_EGENERIC;
374                         delete p_PicMXFSReader;
375                         goto error;
376                     }
377
378                     p_PicMXFSReader->FillPictureDescriptor( PicDesc );
379                     videoReader_t videoReader;
380                     videoReader.p_PicMXFSReader = p_PicMXFSReader;
381                     p_sys->v_videoReader.push_back(videoReader);
382                 } else {                                            /* 2D JPEG2000 */
383                     JP2K::MXFReader *p_PicMXFReader = new ( nothrow ) JP2K::MXFReader();
384                     if( !p_PicMXFReader ) {
385                         retval = VLC_ENOMEM;
386                         goto error;
387                     }
388                     if( !ASDCP_SUCCESS( p_PicMXFReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
389                         msg_Err( p_demux, "File %s could not be opened with ASDCP",
390                                         p_sys->p_dcp->video_reels[i].filename.c_str() );
391                         retval = VLC_EGENERIC;
392                         delete p_PicMXFReader;
393                         goto error;
394                     }
395
396                     p_PicMXFReader->FillPictureDescriptor( PicDesc );
397                     videoReader_t videoReader;
398                     videoReader.p_PicMXFReader = p_PicMXFReader;
399                     p_sys->v_videoReader.push_back(videoReader);
400                 }
401                 es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_JPEG2000 );
402                 fillVideoFmt( &video_format.video, PicDesc.StoredWidth, PicDesc.StoredHeight,
403                                 PicDesc.EditRate.Numerator, PicDesc.EditRate.Denominator );
404
405
406                 if ( i > 0 ) {
407                     if ( p_sys->frame_rate_num != PicDesc.EditRate.Numerator ||
408                             p_sys->frame_rate_denom != PicDesc.EditRate.Denominator )
409                     {
410                         msg_Err( p_demux, "Integrity check failed : different frame rates" );
411                         retval = VLC_EGENERIC;
412                         goto error;
413                     }
414                 }
415                 else
416                 {
417                     p_sys->frame_rate_num   = PicDesc.EditRate.Numerator;
418                     p_sys->frame_rate_denom = PicDesc.EditRate.Denominator;
419                 }
420
421                 p_sys->frames_total += p_sys->p_dcp->video_reels[i].i_duration;
422                 break;
423             }
424             case ESS_MPEG2_VES: {
425
426                 MPEG2::MXFReader *p_VideoMXFReader = new ( nothrow ) MPEG2::MXFReader();
427
428                 videoReader_t videoReader;
429                 videoReader.p_VideoMXFReader = p_VideoMXFReader;
430                 p_sys->v_videoReader.push_back(videoReader);
431
432                 MPEG2::VideoDescriptor  VideoDesc;
433
434                 if( !p_VideoMXFReader ) {
435                     retval = VLC_ENOMEM;
436                     goto error;
437                 }
438
439                 if( !ASDCP_SUCCESS( p_VideoMXFReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
440                     msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->video_reels[i].filename.c_str() );
441                     retval = VLC_EGENERIC;
442                     goto error;
443                 }
444
445                 p_VideoMXFReader->FillVideoDescriptor( VideoDesc );
446
447                 es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_MPGV );
448                 fillVideoFmt( &video_format.video, VideoDesc.StoredWidth, VideoDesc.StoredHeight,
449                               VideoDesc.EditRate.Numerator, VideoDesc.EditRate.Denominator );
450
451
452                 if ( i > 0 ) {
453                     if ( p_sys->frame_rate_num != VideoDesc.EditRate.Numerator ||
454                             p_sys->frame_rate_denom != VideoDesc.EditRate.Denominator)
455                     {
456                         msg_Err( p_demux, "Integrity check failed : different frame rates" );
457                         retval = VLC_EGENERIC;
458                         goto error;
459                     }
460                 }
461                 else
462                 {
463                     p_sys->frame_rate_num   = VideoDesc.EditRate.Numerator;
464                     p_sys->frame_rate_denom = VideoDesc.EditRate.Denominator;
465                 }
466
467                 p_sys->frames_total += p_sys->p_dcp->video_reels[i].i_duration;
468                 break;
469             }
470             default:
471                 msg_Err( p_demux, "Unrecognized video format" );
472                 retval = VLC_EGENERIC;
473                 goto error;
474         }
475     }
476
477     if ( (p_sys->frame_rate_num == 0) || (p_sys->frame_rate_denom == 0) ) {
478         msg_Err(p_demux, "Invalid frame rate (%i/%i)",
479                 p_sys->frame_rate_num, p_sys->frame_rate_denom);
480         retval = VLC_EGENERIC;
481         goto error;
482     }
483
484     if( ( p_sys->p_video_es = es_out_Add( p_demux->out, &video_format ) ) == NULL ) {
485         msg_Err( p_demux, "Failed to add video es" );
486         retval = VLC_EGENERIC;
487         goto error;
488     }
489
490     /* Open audio file */
491     EssenceType_t AudioEssType;
492     EssenceType_t AudioEssTypeCompare;
493
494     if( !p_sys->p_dcp->audio_reels.empty() )
495     {
496         EssenceType( p_sys->p_dcp->audio_reels[0].filename.c_str(), AudioEssType );
497
498         if ( (AudioEssType == ESS_PCM_24b_48k) || (AudioEssType == ESS_PCM_24b_96k) ) {
499             PCM::AudioDescriptor AudioDesc;
500
501             for ( size_t i = 0; i < ( p_sys->p_dcp->audio_reels.size() ); i++)
502             {
503                 if ( i != 0 )
504                 {
505                     EssenceType( p_sys->p_dcp->audio_reels[i].filename.c_str(), AudioEssTypeCompare );
506                     if ( AudioEssTypeCompare != AudioEssType )
507                     {
508                         msg_Err( p_demux, "Integrity check failed : different audio essence types in %s",
509                         p_sys->p_dcp->audio_reels[i].filename.c_str() );
510                         retval = VLC_EGENERIC;
511                         goto error;
512                     }
513                 }
514                 PCM::MXFReader *p_AudioMXFReader = new ( nothrow ) PCM::MXFReader();
515
516                 if( !p_AudioMXFReader ) {
517                     retval = VLC_ENOMEM;
518                     goto error;
519                 }
520
521                 if( !ASDCP_SUCCESS( p_AudioMXFReader->OpenRead( p_sys->p_dcp->audio_reels[i].filename.c_str() ) ) ) {
522                     msg_Err( p_demux, "File %s could not be opened with ASDCP",
523                                     p_sys->p_dcp->audio_reels[i].filename.c_str() );
524                     retval = VLC_EGENERIC;
525                     delete p_AudioMXFReader;
526                     goto error;
527                 }
528
529                 p_AudioMXFReader->FillAudioDescriptor( AudioDesc );
530
531                 if (  (AudioDesc.ChannelCount >= sizeof(pi_channels_aout)/sizeof(uint32_t *))
532                         || (pi_channels_aout[AudioDesc.ChannelCount] == NULL) )
533                 {
534                     msg_Err(p_demux, " DCP module does not support %i channels", AudioDesc.ChannelCount);
535                     retval = VLC_EGENERIC;
536                     delete p_AudioMXFReader;
537                     goto error;
538                 }
539                 audioReader_t audioReader;
540                 audioReader.p_AudioMXFReader = p_AudioMXFReader;
541                 p_sys->v_audioReader.push_back( audioReader );
542
543             }
544             es_format_Init( &audio_format, AUDIO_ES, VLC_CODEC_S24L );
545             if( AudioDesc.AudioSamplingRate.Denominator != 0 )
546                 audio_format.audio.i_rate =
547                     AudioDesc.AudioSamplingRate.Numerator
548                     / AudioDesc.AudioSamplingRate.Denominator;
549             else if ( AudioEssType == ESS_PCM_24b_96k )
550                 audio_format.audio.i_rate = 96000;
551             else
552                 audio_format.audio.i_rate = 48000;
553
554             p_sys->i_audio_buffer = PCM::CalcFrameBufferSize( AudioDesc );
555             if (p_sys->i_audio_buffer == 0) {
556                 msg_Err( p_demux, "Failed to get audio buffer size" );
557                 retval = VLC_EGENERIC;
558                 goto error;
559             }
560
561             audio_format.audio.i_bitspersample = AudioDesc.QuantizationBits;
562             audio_format.audio.i_blockalign    = AudioDesc.BlockAlign;
563             audio_format.audio.i_channels      =
564             p_sys->i_channels                  = AudioDesc.ChannelCount;
565
566             /* Manage channel orders */
567             p_sys->i_chans_to_reorder =  aout_CheckChannelReorder(
568                     pi_channels_aout[AudioDesc.ChannelCount], NULL,
569                     i_channel_mask[AudioDesc.ChannelCount],   p_sys->pi_chan_table );
570
571             if( ( p_sys->p_audio_es = es_out_Add( p_demux->out, &audio_format ) ) == NULL ) {
572                 msg_Err( p_demux, "Failed to add audio es" );
573                 retval = VLC_EGENERIC;
574                 goto error;
575             }
576         } else {
577             msg_Err( p_demux, "The file %s is not a supported AS_DCP essence container",
578                     p_sys->p_dcp->audio_reels[0].filename.c_str() );
579             retval = VLC_EGENERIC;
580             goto error;
581         }
582     }
583     p_demux->pf_demux = Demux;
584     p_demux->pf_control = Control;
585     p_sys->frame_no = p_sys->p_dcp->video_reels[0].i_entrypoint;
586
587     return VLC_SUCCESS;
588 error:
589     CloseDcpAndMxf( p_demux );
590     return retval;
591 }
592
593
594 /*****************************************************************************
595  * Close: module destroy function
596  *****************************************************************************/
597 static inline void Close( vlc_object_t *obj )
598 {
599     demux_t *p_demux = ( demux_t* ) obj;
600     CloseDcpAndMxf( p_demux );
601 }
602
603
604
605 /*****************************************************************************
606  * Demux: DCP Demuxing function
607  *****************************************************************************/
608 static int Demux( demux_t *p_demux )
609 {
610     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
611     block_t *p_video_frame = NULL, *p_audio_frame = NULL;
612
613     PCM::FrameBuffer   AudioFrameBuff( p_sys->i_audio_buffer);
614     AESDecContext video_aes_ctx, audio_aes_ctx;
615
616     /* swaping video reels */
617     if  ( p_sys->frame_no == p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_absolute_end )
618     {
619         if ( p_sys->i_video_reel + 1 == p_sys->v_videoReader.size() )
620         {
621             return 0;
622         }
623         else
624         {
625             p_sys->i_video_reel++;
626         }
627     }
628
629     /* swaping audio reels */
630     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 )
631      {
632          if ( p_sys->i_audio_reel + 1 == p_sys->v_audioReader.size() )
633          {
634              return 0;//should never go there
635          }
636          else
637          {
638              p_sys->i_audio_reel++;
639          }
640      }
641
642     /* video frame */
643
644     /* initialize AES context, if reel is encrypted */
645     if( p_sys->p_dcp->video_reels.size() > p_sys->i_video_reel &&
646         p_sys->p_dcp->video_reels[p_sys->i_video_reel].p_key )
647     {
648         if( ! ASDCP_SUCCESS( video_aes_ctx.InitKey( p_sys->p_dcp->video_reels[p_sys->i_video_reel].p_key->getKey() ) ) )
649         {
650             msg_Err( p_demux, "ASDCP failed to initialize AES key" );
651             goto error;
652         }
653     }
654
655     switch( p_sys->PictureEssType )
656     {
657         case ESS_JPEG_2000:
658         case ESS_JPEG_2000_S:{
659             JP2K::FrameBuffer  PicFrameBuff(FRAME_BUFFER_SIZE);
660             int nextFrame = p_sys->frame_no + p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_correction;
661             if ( ( p_video_frame = block_Alloc( FRAME_BUFFER_SIZE )) == NULL )
662                 goto error;
663
664             if ( ! ASDCP_SUCCESS(
665                     PicFrameBuff.SetData(p_video_frame->p_buffer, FRAME_BUFFER_SIZE)) )
666                 goto error_asdcp;
667             if ( p_sys->PictureEssType == ESS_JPEG_2000_S ) {
668                 if ( ! ASDCP_SUCCESS(
669                         p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFSReader->ReadFrame(nextFrame, JP2K::SP_LEFT, PicFrameBuff, &video_aes_ctx, 0)) ) {
670                     PicFrameBuff.SetData(0,0);
671                     goto error_asdcp;
672                 }
673              } else {
674                 if ( ! ASDCP_SUCCESS(
675                         p_sys->v_videoReader[p_sys->i_video_reel].p_PicMXFReader->ReadFrame(nextFrame, PicFrameBuff, &video_aes_ctx, 0)) ) {
676                     PicFrameBuff.SetData(0,0);
677                     goto error_asdcp;
678                 }
679             }
680             p_video_frame->i_buffer = PicFrameBuff.Size();
681             break;
682         }
683         case ESS_MPEG2_VES: {
684             MPEG2::FrameBuffer VideoFrameBuff(FRAME_BUFFER_SIZE);
685             if ( ( p_video_frame = block_Alloc( FRAME_BUFFER_SIZE )) == NULL )
686                 goto error;
687
688             if ( ! ASDCP_SUCCESS(
689                     VideoFrameBuff.SetData(p_video_frame->p_buffer, FRAME_BUFFER_SIZE)) )
690                 goto error_asdcp;
691
692             if ( ! ASDCP_SUCCESS(
693                     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)) ) {
694                 VideoFrameBuff.SetData(0,0);
695                 goto error_asdcp;
696             }
697
698             p_video_frame->i_buffer = VideoFrameBuff.Size();
699             break;
700         }
701         default:
702             msg_Err( p_demux, "Unrecognized video format" );
703             goto error;
704     }
705
706     p_video_frame->i_length = vlc_tick_from_samples(p_sys->frame_rate_denom, p_sys->frame_rate_num);
707     p_video_frame->i_pts = vlc_tick_from_samples(p_sys->frame_no * p_sys->frame_rate_denom, p_sys->frame_rate_num);
708
709     if( !p_sys->p_dcp->audio_reels.empty() )
710     {
711         /* audio frame */
712         if ( ( p_audio_frame = block_Alloc( p_sys->i_audio_buffer )) == NULL ) {
713             goto error;
714         }
715
716         /* initialize AES context, if reel is encrypted */
717         if( p_sys->p_dcp->audio_reels.size() > p_sys->i_audio_reel &&
718             p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key )
719         {
720             if( ! ASDCP_SUCCESS( audio_aes_ctx.InitKey( p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key->getKey() ) ) )
721             {
722                 msg_Err( p_demux, "ASDCP failed to initialize AES key" );
723                 goto error;
724             }
725         }
726
727         if ( ! ASDCP_SUCCESS(
728                 AudioFrameBuff.SetData(p_audio_frame->p_buffer, p_sys->i_audio_buffer)) ) {
729             goto error_asdcp;
730         }
731
732         if ( ! ASDCP_SUCCESS(
733                 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)) ) {
734             AudioFrameBuff.SetData(0,0);
735             goto error_asdcp;
736         }
737
738         if( p_sys->i_chans_to_reorder )
739             aout_ChannelReorder( p_audio_frame->p_buffer, p_audio_frame->i_buffer,
740                     p_sys->i_channels,
741                     p_sys->pi_chan_table, VLC_CODEC_S24L );
742
743         p_audio_frame->i_buffer = AudioFrameBuff.Size();
744         p_audio_frame->i_length = vlc_tick_from_samples(p_sys->frame_rate_denom, p_sys->frame_rate_num);
745         p_audio_frame->i_pts = vlc_tick_from_samples(p_sys->frame_no * p_sys->frame_rate_denom, p_sys->frame_rate_num);
746         /* Video is the main pts */
747         if ( p_audio_frame->i_pts != p_video_frame->i_pts ) {
748             msg_Err( p_demux, "Audio and video frame pts are not in sync" );
749         }
750     }
751
752     p_sys->i_pts = p_video_frame->i_pts;
753     es_out_SetPCR( p_demux->out, p_sys->i_pts );
754     if(p_video_frame)
755         es_out_Send( p_demux->out, p_sys->p_video_es, p_video_frame );
756     if(p_audio_frame)
757         es_out_Send( p_demux->out, p_sys->p_audio_es, p_audio_frame );
758
759     p_sys->frame_no++;
760
761     return 1;
762
763 error_asdcp:
764     msg_Err( p_demux, "Couldn't read frame with ASDCP");
765 error:
766     if (p_video_frame)
767         block_Release(p_video_frame);
768     if (p_audio_frame)
769         block_Release(p_audio_frame);
770     return -1;
771 }
772
773 /*****************************************************************************
774  * Control: handle the controls
775  *****************************************************************************/
776 static int Control( demux_t *p_demux, int query, va_list args )
777 {
778     double f,*pf;
779     bool *pb;
780     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
781
782     switch ( query )
783     {
784         case DEMUX_CAN_PAUSE:
785         case DEMUX_CAN_CONTROL_PACE:
786             pb = va_arg ( args, bool* );
787             *pb = true;
788             break;
789
790         case DEMUX_CAN_SEEK:
791             pb = va_arg( args, bool * );
792             if( p_sys->PictureEssType != ESS_MPEG2_VES )
793                 *pb = true;
794             else
795                 *pb = false;
796             break;
797
798         case DEMUX_SET_PAUSE_STATE:
799             return VLC_SUCCESS;
800
801         case DEMUX_GET_POSITION:
802             pf = va_arg( args, double * );
803             if( p_sys->frames_total != 0 )
804                 *pf = (double) p_sys->frame_no / (double) p_sys->frames_total;
805             else {
806                 msg_Warn( p_demux, "Total number of frames is 0" );
807                 *pf = 0.0;
808             }
809             break;
810
811         case DEMUX_SET_POSITION:
812             f = va_arg( args, double );
813             p_sys->frame_no = (int) ( f * p_sys->frames_total );
814             break;
815
816         case DEMUX_GET_LENGTH:
817             *va_arg ( args, vlc_tick_t * ) =
818                 vlc_tick_from_sec( p_sys->frames_total * p_sys->frame_rate_denom / p_sys->frame_rate_num );
819             break;
820
821         case DEMUX_GET_TIME:
822             *va_arg( args, vlc_tick_t * ) = __MAX(p_sys->i_pts, 0);
823             break;
824
825         case DEMUX_SET_TIME:
826             p_sys->i_pts = va_arg( args, vlc_tick_t );
827             msg_Warn( p_demux, "DEMUX_SET_TIME"  );
828             p_sys->frame_no = p_sys->i_pts * p_sys->frame_rate_num / ( CLOCK_FREQ * p_sys->frame_rate_denom );
829             es_out_SetPCR(p_demux->out, p_sys->i_pts);
830             es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, p_sys->i_pts );
831             break;
832         case DEMUX_GET_PTS_DELAY:
833             *va_arg( args, vlc_tick_t * ) =
834                 VLC_TICK_FROM_MS(var_InheritInteger( p_demux, "file-caching" ));
835             return VLC_SUCCESS;
836
837
838         default:
839             msg_Warn( p_demux, "Unknown query %d in DCP Control", query );
840             return VLC_EGENERIC;
841     }
842
843     return VLC_SUCCESS;
844 }
845
846
847 /*****************************************************************************
848  * Low-level functions : string manipulation, free function, etc
849  *****************************************************************************/
850 /**
851  * Function to fill video_format_t fields for an elementary stream
852  * @param fmt video format structure
853  * @param width picture width
854  * @param height picture height
855  * @param frame_rate_num video frame rate numerator
856  * @param frame_rate_denom video frame rate denominator
857  */
858 static inline void fillVideoFmt( video_format_t * fmt, unsigned int width, unsigned int height, unsigned int frame_rate_num, unsigned int frame_rate_denom )
859 {
860     fmt->i_width = width;
861     fmt->i_height = height;
862     /* As input are square pixels let VLC  or decoder fix SAR, origin,
863      * and visible area */
864     fmt->i_frame_rate = frame_rate_num;
865     fmt->i_frame_rate_base = frame_rate_denom;
866 }
867
868 /**
869  * Function to free memory in case of error or when closing the module
870  * @param p_demux DCP access-demux
871  */
872
873
874 void CloseDcpAndMxf( demux_t *p_demux )
875 {
876     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
877     /* close the files */
878     switch( p_sys->PictureEssType )
879     {
880         case ESS_UNKNOWN:
881             break;
882         case ESS_JPEG_2000:
883             for ( size_t i = 0; i < p_sys->v_videoReader.size(); i++ )
884             {
885                 if( p_sys->v_videoReader[i].p_PicMXFReader )
886                     p_sys->v_videoReader[i].p_PicMXFReader->Close();
887             }
888             break;
889         case ESS_JPEG_2000_S:
890             for ( size_t i = 0; i < p_sys->v_videoReader.size(); i++ )
891             {
892                 if( p_sys->v_videoReader[i].p_PicMXFSReader )
893                     p_sys->v_videoReader[i].p_PicMXFSReader->Close();
894             }
895             break;
896         case ESS_MPEG2_VES:
897             for ( size_t i = 0; i < p_sys->v_videoReader.size(); i++ )
898             {
899                 if( p_sys->v_videoReader[i].p_VideoMXFReader )
900                     p_sys->v_videoReader[i].p_VideoMXFReader->Close();
901             }
902             break;
903         default:
904             break;
905     }
906
907     for ( size_t i = 0; i < p_sys->v_audioReader.size(); i++ )
908     {
909         if( p_sys->v_audioReader[i].p_AudioMXFReader )
910             p_sys->v_audioReader[i].p_AudioMXFReader->Close();
911     }
912
913     delete( p_sys );
914 }
915
916
917 /*****************************************************************************
918  * DCP init
919  *****************************************************************************/
920
921 /**
922  * Function to handle the operations with the DCP directory.
923  * @param p_demux Demux pointer.
924  * @return Integer according to the success or not of the process.
925  */
926 int dcpInit ( demux_t *p_demux )
927 {
928     int retval;
929
930     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
931     dcp_t *p_dcp = p_sys->p_dcp;
932
933     p_dcp->path = p_demux->psz_filepath;
934     /* Add a '/' in end of path if needed */
935     if ( *(p_dcp->path).rbegin() != '/')
936         p_dcp->path.append( "/" );
937
938     /* Parsing XML files to get audio and video files */
939     msg_Dbg( p_demux, "parsing XML files..." );
940     if( ( retval = parseXML( p_demux ) ) )
941         return retval;
942
943     msg_Dbg(p_demux, "parsing XML files done");
944
945     return VLC_SUCCESS;
946 }
947
948
949 /*****************************************************************************
950  * functions for XML parsing
951  *****************************************************************************/
952
953 /**
954  * Function to retrieve the path to the ASSETMAP file.
955  * @param p_demux DCP access_demux.
956  */
957 static std::string assetmapPath( demux_t * p_demux )
958 {
959     DIR *dir = NULL;
960     struct dirent *ent = NULL;
961     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
962     dcp_t *p_dcp = p_sys->p_dcp;
963     std::string result;
964
965     if( ( dir = opendir (p_dcp->path.c_str() ) ) != NULL )
966     {
967         /* print all the files and directories within directory */
968         while( ( ent = readdir ( dir ) ) != NULL )
969         {
970             if( strcasecmp( "assetmap", ent->d_name ) == 0 || strcasecmp( "assetmap.xml", ent->d_name ) == 0 )
971             {
972                 /* copy of "path" in "res" */
973                 result = p_dcp->path;
974                 result.append( ent->d_name );
975                 break;
976             }
977         }
978         closedir( dir );
979     }
980     else
981         msg_Err( p_demux, "Could not open the directory: %s", p_dcp->path.c_str() );
982
983     /* if no assetmap file */
984     if( result.empty() )
985         msg_Err( p_demux, "No ASSETMAP found in the directory: %s", p_dcp->path.c_str() );
986
987     return result;
988 }
989
990
991 /**
992  * Function which parses XML files in DCP directory in order to get video and audio files
993  * @param p_demux Demux pointer.
994  * @return Integer according to the success or not of the operation
995  */
996 int parseXML ( demux_t * p_demux )
997 {
998     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
999     int retval;
1000
1001     std::string assetmap_path = assetmapPath( p_demux );
1002     /* We get the ASSETMAP file path */
1003     if( assetmap_path.empty() )
1004         return VLC_EGENERIC;
1005
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_sys->p_dcp );
1009     if( ( retval = assetmap->Parse() ) )
1010         return retval;
1011
1012     delete assetmap;
1013     return VLC_SUCCESS; /* TODO : perform checking on XML parsing */
1014 }