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