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     set_description( N_( "Digital Cinema Package module" ) )
80     set_capability( "access_demux", 0 )
81     set_category( CAT_INPUT )
82     set_subcategory( SUBCAT_INPUT_ACCESS )
83     add_loadfile( "kdm", "", KDM_HELP_TEXT, KDM_HELP_LONG_TEXT, false )
84     set_callbacks( Open, Close )
85 vlc_module_end()
86 
87 //! Kind of MXF MEDIA TYPE
88 typedef enum MxfMedia_t {
89     MXF_UNKNOWN = 0,
90     MXF_PICTURE,
91     MXF_AUDIO,
92 } MxfMedia_t;
93 
94 union videoReader_t
95 {
96    /* JPEG2000 essence type */
97    ASDCP::JP2K::MXFReader *p_PicMXFReader;
98 
99    /* JPEG2000 stereoscopic essence type */
100    ASDCP::JP2K::MXFSReader *p_PicMXFSReader;
101 
102    /* MPEG2 essence type */
103    ASDCP::MPEG2::MXFReader *p_VideoMXFReader;
104 };
105 
106 struct audioReader_t
107 {
108     PCM::MXFReader *p_AudioMXFReader;
109 };
110 
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).
119 
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.
121 */
122 
123 class demux_sys_t
124 {
125  public:
126     /* ASDCP Picture Essence Type */
127     EssenceType_t PictureEssType;
128 
129     /* ASDCP Video MXF Reader */
130     std::vector<videoReader_t> v_videoReader;
131 
132     /* ASDCP Audio MXF Reader */
133     std::vector<audioReader_t> v_audioReader;
134 
135     /* audio buffer size */
136     uint32_t i_audio_buffer;
137 
138     /* elementary streams */
139     es_out_id_t *p_video_es;
140     es_out_id_t *p_audio_es;
141 
142     /* DCP object */
143     dcp_t *p_dcp;
144 
145     /* current absolute frame number */
146     uint32_t frame_no;
147 
148     /* frame rate */
149     int frame_rate_num;
150     int frame_rate_denom;
151 
152     /* total number of frames */
153     uint32_t frames_total;
154 
155     /* current video reel */
156     unsigned int i_video_reel;
157 
158     /* current audio reel */
159     unsigned int i_audio_reel;
160 
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;
164 
165     mtime_t i_pts;
166 
demux_sys_t()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 ),
178         i_pts( 0 )
179     {}
180 
~demux_sys_t()181     ~demux_sys_t()
182     {
183         switch ( PictureEssType )
184         {
185             case ESS_UNKNOWN:
186                 break;
187             case ESS_JPEG_2000:
188                 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
189                 {
190                     delete v_videoReader[i].p_PicMXFReader;
191                 }
192                 break;
193             case ESS_JPEG_2000_S:
194                 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
195                 {
196                     delete v_videoReader[i].p_PicMXFSReader;
197                 }
198                 break;
199             case ESS_MPEG2_VES:
200                 for ( unsigned int i = 0; i < v_videoReader.size(); i++ )
201                 {
202                     delete v_videoReader[i].p_VideoMXFReader;
203                 }
204                 break;
205             default:
206                 break;
207         }
208 
209         for ( unsigned int i = 0; i < v_audioReader.size(); i++ )
210         {
211             delete v_audioReader[i].p_AudioMXFReader;
212         }
213 
214         delete p_dcp;
215     }
216 };
217 
218 /*TODO: basic correlation between SMPTE S428-3/S429-2
219  * Real sound is more complex with case of left/right surround, ...
220  * and hearing impaired/Narration channels */
221 
222 /* 1 channel: mono */
223 static const uint32_t i_channels_1[] =
224 { AOUT_CHAN_LEFT, 0 };
225 
226 /* 2 channels: stereo */
227 static const uint32_t i_channels_2[]=
228 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 };
229 
230 /* 4 channels */
231 static const uint32_t i_channels_4[] =
232 {   AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
233     AOUT_CHAN_LFE, 0  };
234 
235 /* 6 channels: 5.1 */
236 static const uint32_t i_channels_6[] =
237 {   AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,      AOUT_CHAN_CENTER,
238     AOUT_CHAN_LFE,  AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,
239     0 };
240 
241 /* 7 channels: 6.1 */
242 static const uint32_t i_channels_7[] =
243 {   AOUT_CHAN_LEFT,       AOUT_CHAN_RIGHT,    AOUT_CHAN_CENTER,
244     AOUT_CHAN_LFE,        AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
245     AOUT_CHAN_REARCENTER, 0  };
246 
247 /* 8 channels:  7.1 */
248 static const uint32_t i_channels_8[] =
249 {   AOUT_CHAN_LEFT,        AOUT_CHAN_RIGHT,      AOUT_CHAN_CENTER,
250     AOUT_CHAN_LFE,         AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,
251     AOUT_CHAN_MIDDLELEFT,  AOUT_CHAN_MIDDLERIGHT, 0 };
252 
253 /* 9 channels; 8.1 */
254 static const uint32_t i_channels_9[] =
255 {   AOUT_CHAN_LEFT,        AOUT_CHAN_RIGHT,      AOUT_CHAN_CENTER,
256     AOUT_CHAN_LFE,         AOUT_CHAN_REARLEFT,   AOUT_CHAN_REARRIGHT,
257     AOUT_CHAN_MIDDLELEFT,  AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_REARCENTER, 0 };
258 
259 static const uint32_t *pi_channels_aout [] =
260 {   NULL,
261     i_channels_1,
262     i_channels_2,
263     NULL,
264     i_channels_4,
265     NULL,
266     i_channels_6,
267     i_channels_7,
268     i_channels_8,
269     i_channels_9 };
270 
271 static const unsigned i_channel_mask[] =
272 {    0,
273     AOUT_CHAN_LEFT,
274     AOUT_CHANS_STEREO,
275     0,
276     AOUT_CHANS_3_1,
277     0,
278     AOUT_CHANS_5_1,
279     AOUT_CHANS_6_1_MIDDLE,
280     AOUT_CHANS_7_1,
281     AOUT_CHANS_8_1 };
282 
283 /*****************************************************************************
284  * Local prototypes
285  *****************************************************************************/
286 
287 static int Demux( demux_t * );
288 static int Control( demux_t *, int, va_list );
289 
290 int dcpInit ( demux_t *p_demux );
291 int parseXML ( demux_t * p_demux );
292 static inline void fillVideoFmt(
293         video_format_t * fmt, unsigned int width, unsigned int height,
294         unsigned int frame_rate_num, unsigned int frame_rate_denom );
295 void CloseDcpAndMxf( demux_t *p_demux );
296 
297 
298 
299 /*****************************************************************************
300  * Open: module init function
301  *****************************************************************************/
Open(vlc_object_t * obj)302 static int Open( vlc_object_t *obj )
303 {
304     demux_t *p_demux = ( demux_t* ) obj;
305     demux_sys_t *p_sys;
306     es_format_t video_format, audio_format;
307     int retval;
308 
309     if( !p_demux->psz_file )
310         return VLC_EGENERIC;
311 
312     p_sys = new ( nothrow ) demux_sys_t();
313     if( unlikely( p_sys == NULL ) ) {
314         return VLC_ENOMEM;
315     }
316     p_demux->p_sys = p_sys;
317 
318     /* Allocate DCP object */
319     dcp_t *p_dcp = new ( nothrow ) dcp_t;
320     if( unlikely( p_dcp == NULL ) ) {
321         delete  p_sys;
322         return VLC_ENOMEM;
323     }
324     p_sys->p_dcp = p_dcp;
325 
326 
327     /* handle the DCP directory, saving the paths for audio and video file, returning error if unsuccessful */
328     if( ( retval = dcpInit( p_demux ) ) )
329         goto error;
330 
331     /* Open video file */
332     EssenceType_t essInter;
333     for ( size_t i = 0; i < ( p_sys->p_dcp->video_reels.size() ); i++ )
334     {
335         EssenceType( p_sys->p_dcp->video_reels[i].filename.c_str(), essInter );
336         if ( i == 0 )
337         {
338             p_sys->PictureEssType = essInter;
339         }
340         else
341         {
342             if ( essInter != p_sys->PictureEssType )
343             {
344                 msg_Err( p_demux, "Integrity check failed : different essence containers" );
345                 retval = VLC_EGENERIC;
346                 goto error;
347             }
348         }
349 
350         switch( essInter )
351         {
352             case ESS_UNKNOWN:
353                 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() );
354                 retval = VLC_EGENERIC;
355                 goto error;
356 
357             case ESS_JPEG_2000:
358             case ESS_JPEG_2000_S: {
359                 JP2K::PictureDescriptor PicDesc;
360                 if (p_sys->PictureEssType == ESS_JPEG_2000_S) {     /* 3D JPEG2000 */
361                     JP2K::MXFSReader * p_PicMXFSReader = new ( nothrow ) JP2K::MXFSReader();
362 
363                     if( !p_PicMXFSReader) {
364                         retval = VLC_ENOMEM;
365                         goto error;
366                     }
367                     if( !ASDCP_SUCCESS( p_PicMXFSReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
368                         msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->video_reels[i].filename.c_str() );
369                         retval = VLC_EGENERIC;
370                         delete p_PicMXFSReader;
371                         goto error;
372                     }
373 
374                     p_PicMXFSReader->FillPictureDescriptor( PicDesc );
375                     videoReader_t videoReader;
376                     videoReader.p_PicMXFSReader = p_PicMXFSReader;
377                     p_sys->v_videoReader.push_back(videoReader);
378                 } else {                                            /* 2D JPEG2000 */
379                     JP2K::MXFReader *p_PicMXFReader = new ( nothrow ) JP2K::MXFReader();
380                     if( !p_PicMXFReader ) {
381                         retval = VLC_ENOMEM;
382                         goto error;
383                     }
384                     if( !ASDCP_SUCCESS( p_PicMXFReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
385                         msg_Err( p_demux, "File %s could not be opened with ASDCP",
386                                         p_sys->p_dcp->video_reels[i].filename.c_str() );
387                         retval = VLC_EGENERIC;
388                         delete p_PicMXFReader;
389                         goto error;
390                     }
391 
392                     p_PicMXFReader->FillPictureDescriptor( PicDesc );
393                     videoReader_t videoReader;
394                     videoReader.p_PicMXFReader = p_PicMXFReader;
395                     p_sys->v_videoReader.push_back(videoReader);
396                 }
397                 es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_JPEG2000 );
398                 fillVideoFmt( &video_format.video, PicDesc.StoredWidth, PicDesc.StoredHeight,
399                                 PicDesc.EditRate.Numerator, PicDesc.EditRate.Denominator );
400 
401 
402                 if ( i > 0 ) {
403                     if ( p_sys->frame_rate_num != PicDesc.EditRate.Numerator ||
404                             p_sys->frame_rate_denom != PicDesc.EditRate.Denominator )
405                     {
406                         msg_Err( p_demux, "Integrity check failed : different frame rates" );
407                         retval = VLC_EGENERIC;
408                         goto error;
409                     }
410                 }
411                 else
412                 {
413                     p_sys->frame_rate_num   = PicDesc.EditRate.Numerator;
414                     p_sys->frame_rate_denom = PicDesc.EditRate.Denominator;
415                 }
416 
417                 p_sys->frames_total += p_sys->p_dcp->video_reels[i].i_duration;
418                 break;
419             }
420             case ESS_MPEG2_VES: {
421 
422                 MPEG2::MXFReader *p_VideoMXFReader = new ( nothrow ) MPEG2::MXFReader();
423 
424                 videoReader_t videoReader;
425                 videoReader.p_VideoMXFReader = p_VideoMXFReader;
426                 p_sys->v_videoReader.push_back(videoReader);
427 
428                 MPEG2::VideoDescriptor  VideoDesc;
429 
430                 if( !p_VideoMXFReader ) {
431                     retval = VLC_ENOMEM;
432                     goto error;
433                 }
434 
435                 if( !ASDCP_SUCCESS( p_VideoMXFReader->OpenRead( p_sys->p_dcp->video_reels[i].filename.c_str() ) ) ) {
436                     msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->video_reels[i].filename.c_str() );
437                     retval = VLC_EGENERIC;
438                     goto error;
439                 }
440 
441                 p_VideoMXFReader->FillVideoDescriptor( VideoDesc );
442 
443                 es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_MPGV );
444                 fillVideoFmt( &video_format.video, VideoDesc.StoredWidth, VideoDesc.StoredHeight,
445                               VideoDesc.EditRate.Numerator, VideoDesc.EditRate.Denominator );
446 
447 
448                 if ( i > 0 ) {
449                     if ( p_sys->frame_rate_num != VideoDesc.EditRate.Numerator ||
450                             p_sys->frame_rate_denom != VideoDesc.EditRate.Denominator)
451                     {
452                         msg_Err( p_demux, "Integrity check failed : different frame rates" );
453                         retval = VLC_EGENERIC;
454                         goto error;
455                     }
456                 }
457                 else
458                 {
459                     p_sys->frame_rate_num   = VideoDesc.EditRate.Numerator;
460                     p_sys->frame_rate_denom = VideoDesc.EditRate.Denominator;
461                 }
462 
463                 p_sys->frames_total += p_sys->p_dcp->video_reels[i].i_duration;
464                 break;
465             }
466             default:
467                 msg_Err( p_demux, "Unrecognized video format" );
468                 retval = VLC_EGENERIC;
469                 goto error;
470         }
471     }
472 
473     if ( (p_sys->frame_rate_num == 0) || (p_sys->frame_rate_denom == 0) ) {
474         msg_Err(p_demux, "Invalid frame rate (%i/%i)",
475                 p_sys->frame_rate_num, p_sys->frame_rate_denom);
476         retval = VLC_EGENERIC;
477         goto error;
478     }
479 
480     if( ( p_sys->p_video_es = es_out_Add( p_demux->out, &video_format ) ) == NULL ) {
481         msg_Err( p_demux, "Failed to add video es" );
482         retval = VLC_EGENERIC;
483         goto error;
484     }
485 
486     /* Open audio file */
487     EssenceType_t AudioEssType;
488     EssenceType_t AudioEssTypeCompare;
489 
490     if( !p_sys->p_dcp->audio_reels.empty() )
491     {
492         EssenceType( p_sys->p_dcp->audio_reels[0].filename.c_str(), AudioEssType );
493 
494         if ( (AudioEssType == ESS_PCM_24b_48k) || (AudioEssType == ESS_PCM_24b_96k) ) {
495             PCM::AudioDescriptor AudioDesc;
496 
497             for ( size_t i = 0; i < ( p_sys->p_dcp->audio_reels.size() ); i++)
498             {
499                 if ( i != 0 )
500                 {
501                     EssenceType( p_sys->p_dcp->audio_reels[i].filename.c_str(), AudioEssTypeCompare );
502                     if ( AudioEssTypeCompare != AudioEssType )
503                     {
504                         msg_Err( p_demux, "Integrity check failed : different audio essence types in %s",
505                         p_sys->p_dcp->audio_reels[i].filename.c_str() );
506                         retval = VLC_EGENERIC;
507                         goto error;
508                     }
509                 }
510                 PCM::MXFReader *p_AudioMXFReader = new ( nothrow ) PCM::MXFReader();
511 
512                 if( !p_AudioMXFReader ) {
513                     retval = VLC_ENOMEM;
514                     goto error;
515                 }
516 
517                 if( !ASDCP_SUCCESS( p_AudioMXFReader->OpenRead( p_sys->p_dcp->audio_reels[i].filename.c_str() ) ) ) {
518                     msg_Err( p_demux, "File %s could not be opened with ASDCP",
519                                     p_sys->p_dcp->audio_reels[i].filename.c_str() );
520                     retval = VLC_EGENERIC;
521                     delete p_AudioMXFReader;
522                     goto error;
523                 }
524 
525                 p_AudioMXFReader->FillAudioDescriptor( AudioDesc );
526 
527                 if (  (AudioDesc.ChannelCount >= sizeof(pi_channels_aout)/sizeof(uint32_t *))
528                         || (pi_channels_aout[AudioDesc.ChannelCount] == NULL) )
529                 {
530                     msg_Err(p_demux, " DCP module does not support %i channels", AudioDesc.ChannelCount);
531                     retval = VLC_EGENERIC;
532                     delete p_AudioMXFReader;
533                     goto error;
534                 }
535                 audioReader_t audioReader;
536                 audioReader.p_AudioMXFReader = p_AudioMXFReader;
537                 p_sys->v_audioReader.push_back( audioReader );
538 
539             }
540             es_format_Init( &audio_format, AUDIO_ES, VLC_CODEC_S24L );
541             if( AudioDesc.AudioSamplingRate.Denominator != 0 )
542                 audio_format.audio.i_rate =
543                     AudioDesc.AudioSamplingRate.Numerator
544                     / AudioDesc.AudioSamplingRate.Denominator;
545             else if ( AudioEssType == ESS_PCM_24b_96k )
546                 audio_format.audio.i_rate = 96000;
547             else
548                 audio_format.audio.i_rate = 48000;
549 
550             p_sys->i_audio_buffer = PCM::CalcFrameBufferSize( AudioDesc );
551             if (p_sys->i_audio_buffer == 0) {
552                 msg_Err( p_demux, "Failed to get audio buffer size" );
553                 retval = VLC_EGENERIC;
554                 goto error;
555             }
556 
557             audio_format.audio.i_bitspersample = AudioDesc.QuantizationBits;
558             audio_format.audio.i_blockalign    = AudioDesc.BlockAlign;
559             audio_format.audio.i_channels      =
560             p_sys->i_channels                  = AudioDesc.ChannelCount;
561 
562             /* Manage channel orders */
563             p_sys->i_chans_to_reorder =  aout_CheckChannelReorder(
564                     pi_channels_aout[AudioDesc.ChannelCount], NULL,
565                     i_channel_mask[AudioDesc.ChannelCount],   p_sys->pi_chan_table );
566 
567             if( ( p_sys->p_audio_es = es_out_Add( p_demux->out, &audio_format ) ) == NULL ) {
568                 msg_Err( p_demux, "Failed to add audio es" );
569                 retval = VLC_EGENERIC;
570                 goto error;
571             }
572         } else {
573             msg_Err( p_demux, "The file %s is not a supported AS_DCP essence container",
574                     p_sys->p_dcp->audio_reels[0].filename.c_str() );
575             retval = VLC_EGENERIC;
576             goto error;
577         }
578     }
579     p_demux->pf_demux = Demux;
580     p_demux->pf_control = Control;
581     p_sys->frame_no = p_sys->p_dcp->video_reels[0].i_entrypoint;
582 
583     return VLC_SUCCESS;
584 error:
585     CloseDcpAndMxf( p_demux );
586     return retval;
587 }
588 
589 
590 /*****************************************************************************
591  * Close: module destroy function
592  *****************************************************************************/
Close(vlc_object_t * obj)593 static inline void Close( vlc_object_t *obj )
594 {
595     demux_t *p_demux = ( demux_t* ) obj;
596     CloseDcpAndMxf( p_demux );
597 }
598 
599 
600 
601 /*****************************************************************************
602  * Demux: DCP Demuxing function
603  *****************************************************************************/
Demux(demux_t * p_demux)604 static int Demux( demux_t *p_demux )
605 {
606     demux_sys_t *p_sys = p_demux->p_sys;
607     block_t *p_video_frame = NULL, *p_audio_frame = NULL;
608 
609     PCM::FrameBuffer   AudioFrameBuff( p_sys->i_audio_buffer);
610     AESDecContext video_aes_ctx, audio_aes_ctx;
611 
612     /* swaping video reels */
613     if  ( p_sys->frame_no == p_sys->p_dcp->video_reels[p_sys->i_video_reel].i_absolute_end )
614     {
615         if ( p_sys->i_video_reel + 1 == p_sys->v_videoReader.size() )
616         {
617             return 0;
618         }
619         else
620         {
621             p_sys->i_video_reel++;
622         }
623     }
624 
625     /* swaping audio reels */
626     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 )
627      {
628          if ( p_sys->i_audio_reel + 1 == p_sys->v_audioReader.size() )
629          {
630              return 0;//should never go there
631          }
632          else
633          {
634              p_sys->i_audio_reel++;
635          }
636      }
637 
638     /* video frame */
639 
640     /* initialize AES context, if reel is encrypted */
641     if( 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 )
643     {
644         if( ! ASDCP_SUCCESS( video_aes_ctx.InitKey( p_sys->p_dcp->video_reels[p_sys->i_video_reel].p_key->getKey() ) ) )
645         {
646             msg_Err( p_demux, "ASDCP failed to initialize AES key" );
647             goto error;
648         }
649     }
650 
651     switch( p_sys->PictureEssType )
652     {
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;
659 
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;
668                 }
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;
674                 }
675             }
676             p_video_frame->i_buffer = PicFrameBuff.Size();
677             break;
678         }
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;
683 
684             if ( ! ASDCP_SUCCESS(
685                     VideoFrameBuff.SetData(p_video_frame->p_buffer, FRAME_BUFFER_SIZE)) )
686                 goto error_asdcp;
687 
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;
692             }
693 
694             p_video_frame->i_buffer = VideoFrameBuff.Size();
695             break;
696         }
697         default:
698             msg_Err( p_demux, "Unrecognized video format" );
699             goto error;
700     }
701 
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;
704 
705     if( !p_sys->p_dcp->audio_reels.empty() )
706     {
707         /* audio frame */
708         if ( ( p_audio_frame = block_Alloc( p_sys->i_audio_buffer )) == NULL ) {
709             goto error;
710         }
711 
712         /* initialize AES context, if reel is encrypted */
713         if( p_sys->p_dcp->audio_reels.size() > p_sys->i_audio_reel &&
714             p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key )
715         {
716             if( ! ASDCP_SUCCESS( audio_aes_ctx.InitKey( p_sys->p_dcp->audio_reels[p_sys->i_audio_reel].p_key->getKey() ) ) )
717             {
718                 msg_Err( p_demux, "ASDCP failed to initialize AES key" );
719                 goto error;
720             }
721         }
722 
723         if ( ! ASDCP_SUCCESS(
724                 AudioFrameBuff.SetData(p_audio_frame->p_buffer, p_sys->i_audio_buffer)) ) {
725             goto error_asdcp;
726         }
727 
728         if ( ! ASDCP_SUCCESS(
729                 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)) ) {
730             AudioFrameBuff.SetData(0,0);
731             goto error_asdcp;
732         }
733 
734         if( p_sys->i_chans_to_reorder )
735             aout_ChannelReorder( p_audio_frame->p_buffer, p_audio_frame->i_buffer,
736                     p_sys->i_channels,
737                     p_sys->pi_chan_table, VLC_CODEC_S24L );
738 
739         p_audio_frame->i_buffer = AudioFrameBuff.Size();
740         p_audio_frame->i_length = CLOCK_FREQ * p_sys->frame_rate_denom / p_sys->frame_rate_num;
741         p_audio_frame->i_pts = CLOCK_FREQ * p_sys->frame_no * p_sys->frame_rate_denom / p_sys->frame_rate_num;
742         /* Video is the main pts */
743         if ( p_audio_frame->i_pts != p_video_frame->i_pts ) {
744             msg_Err( p_demux, "Audio and video frame pts are not in sync" );
745         }
746     }
747 
748     p_sys->i_pts = p_video_frame->i_pts;
749     es_out_SetPCR( p_demux->out, p_sys->i_pts );
750     if(p_video_frame)
751         es_out_Send( p_demux->out, p_sys->p_video_es, p_video_frame );
752     if(p_audio_frame)
753         es_out_Send( p_demux->out, p_sys->p_audio_es, p_audio_frame );
754 
755     p_sys->frame_no++;
756 
757     return 1;
758 
759 error_asdcp:
760     msg_Err( p_demux, "Couldn't read frame with ASDCP");
761 error:
762     if (p_video_frame)
763         block_Release(p_video_frame);
764     if (p_audio_frame)
765         block_Release(p_audio_frame);
766     return -1;
767 }
768 
769 /*****************************************************************************
770  * Control: handle the controls
771  *****************************************************************************/
Control(demux_t * p_demux,int query,va_list args)772 static int Control( demux_t *p_demux, int query, va_list args )
773 {
774     double f,*pf;
775     bool *pb;
776     int64_t *pi64, i64;
777     demux_sys_t *p_sys = p_demux->p_sys;
778 
779     switch ( query )
780     {
781         case DEMUX_CAN_PAUSE:
782         case DEMUX_CAN_CONTROL_PACE:
783             pb = va_arg ( args, bool* );
784             *pb = true;
785             break;
786 
787         case DEMUX_CAN_SEEK:
788             pb = va_arg( args, bool * );
789             if( p_sys->PictureEssType != ESS_MPEG2_VES )
790                 *pb = true;
791             else
792                 *pb = false;
793             break;
794 
795         case DEMUX_SET_PAUSE_STATE:
796             return VLC_SUCCESS;
797 
798         case DEMUX_GET_POSITION:
799             pf = va_arg( args, double * );
800             if( p_sys->frames_total != 0 )
801                 *pf = (double) p_sys->frame_no / (double) p_sys->frames_total;
802             else {
803                 msg_Warn( p_demux, "Total number of frames is 0" );
804                 *pf = 0.0;
805             }
806             break;
807 
808         case DEMUX_SET_POSITION:
809             f = va_arg( args, double );
810             p_sys->frame_no = (int) ( f * p_sys->frames_total );
811             break;
812 
813         case DEMUX_GET_LENGTH:
814             pi64 = va_arg ( args, int64_t * );
815             *pi64 =  ( p_sys->frames_total * p_sys->frame_rate_denom / p_sys->frame_rate_num ) * CLOCK_FREQ;
816             break;
817 
818         case DEMUX_GET_TIME:
819             pi64 = va_arg( args, int64_t * );
820             *pi64 = p_sys->i_pts >= 0 ? p_sys->i_pts : 0;
821             break;
822 
823         case DEMUX_SET_TIME:
824             i64 = va_arg( args, int64_t );
825             msg_Warn( p_demux, "DEMUX_SET_TIME"  );
826             p_sys->frame_no = i64 * p_sys->frame_rate_num / ( CLOCK_FREQ * p_sys->frame_rate_denom );
827             p_sys->i_pts= i64;
828             es_out_SetPCR(p_demux->out, p_sys->i_pts);
829             es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, ( mtime_t ) i64 );
830             break;
831         case DEMUX_GET_PTS_DELAY:
832             pi64 = va_arg( args, int64_t * );
833             *pi64 =
834                 INT64_C(1000) * 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  */
fillVideoFmt(video_format_t * fmt,unsigned int width,unsigned int height,unsigned int frame_rate_num,unsigned int frame_rate_denom)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 
CloseDcpAndMxf(demux_t * p_demux)874 void CloseDcpAndMxf( demux_t *p_demux )
875 {
876     demux_sys_t *p_sys = 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  */
dcpInit(demux_t * p_demux)926 int dcpInit ( demux_t *p_demux )
927 {
928     int retval;
929 
930     demux_sys_t *p_sys = p_demux->p_sys;
931     dcp_t *p_dcp = p_sys->p_dcp;
932 
933     p_dcp->path = p_demux->psz_file;
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  */
assetmapPath(demux_t * p_demux)957 static std::string assetmapPath( demux_t * p_demux )
958 {
959     DIR *dir = NULL;
960     struct dirent *ent = NULL;
961     dcp_t *p_dcp = p_demux->p_sys->p_dcp;
962     std::string result;
963 
964     if( ( dir = opendir (p_dcp->path.c_str() ) ) != NULL )
965     {
966         /* print all the files and directories within directory */
967         while( ( ent = readdir ( dir ) ) != NULL )
968         {
969             if( strcasecmp( "assetmap", ent->d_name ) == 0 || strcasecmp( "assetmap.xml", ent->d_name ) == 0 )
970             {
971                 /* copy of "path" in "res" */
972                 result = p_dcp->path;
973                 result.append( ent->d_name );
974                 break;
975             }
976         }
977         closedir( dir );
978     }
979     else
980         msg_Err( p_demux, "Could not open the directory: %s", p_dcp->path.c_str() );
981 
982     /* if no assetmap file */
983     if( result.empty() )
984         msg_Err( p_demux, "No ASSETMAP found in the directory: %s", p_dcp->path.c_str() );
985 
986     return result;
987 }
988 
989 
990 /**
991  * Function which parses XML files in DCP directory in order to get video and audio files
992  * @param p_demux Demux pointer.
993  * @return Integer according to the success or not of the operation
994  */
parseXML(demux_t * p_demux)995 int parseXML ( demux_t * p_demux )
996 {
997     int retval;
998 
999     std::string assetmap_path = assetmapPath( p_demux );
1000     /* We get the ASSETMAP file path */
1001     if( assetmap_path.empty() )
1002         return VLC_EGENERIC;
1003 
1004     /* We parse the ASSETMAP File in order to get CPL File path, PKL File path
1005      and to store UID/Path of all files in DCP directory (except ASSETMAP file) */
1006     AssetMap *assetmap = new (nothrow) AssetMap( p_demux, assetmap_path, p_demux->p_sys->p_dcp );
1007     if( ( retval = assetmap->Parse() ) )
1008         return retval;
1009 
1010     delete assetmap;
1011     return VLC_SUCCESS; /* TODO : perform checking on XML parsing */
1012 }
1013