1 /*
2 * multiplexor.cpp: Program/System stream Multiplex despatcher
3 *
4 * Copyright (C) 2003 Andrew Stevens <andrew.stevens@philips.com>
5 *
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU General Public License
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #define STREAM_LOGGING
22 #include <config.h>
23 #include <math.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <mjpeg_types.h>
28 #include <mjpeg_logging.h>
29 #include <format_codes.h>
30
31 #include "interact.hpp"
32 #include "videostrm.hpp"
33 #include "stillsstream.hpp"
34 #include "audiostrm.hpp"
35 #ifdef ZALPHA
36 #include "zalphastrm.hpp"
37 #endif
38 #include "multiplexor.hpp"
39
40
41 /****************
42 *
43 * Constructor - sets up per-run stuff and initialised parameters
44 * that control syntax of generated stream from the job options set
45 * by the user.
46 *
47 ***************/
48
Multiplexor(MultiplexJob & job,OutputStream & output)49 Multiplexor::Multiplexor(MultiplexJob &job, OutputStream &output)
50 {
51 underrun_ignore = 0;
52 underruns = 0;
53 start_of_new_pack = false;
54 InitSyntaxParameters(job);
55 InitInputStreams(job);
56
57 psstrm = new PS_Stream(mpeg, sector_size, output, max_segment_size );
58
59 }
60
61
62 /******************************************************************
63 *
64 * Initialisation of stream syntax paramters based on selected user
65 * options. Depending of mux_format some selections may only act as
66 * defaults or may simply be ignored if they are inconsistent with the
67 * selected output format.
68 *
69 ******************************************************************/
70
71
InitSyntaxParameters(MultiplexJob & job)72 void Multiplexor::InitSyntaxParameters(MultiplexJob &job)
73 {
74 seg_starts_with_video = false;
75 audio_buffer_size = 4 * 1024;
76 mux_format = job.mux_format;
77 vbr = job.VBR;
78 packets_per_pack = job.packets_per_pack;
79 data_rate = job.data_rate;
80 mpeg = job.mpeg;
81 always_sys_header_in_pack = job.always_system_headers;
82 sector_transport_size = job.sector_size;
83 sector_size = job.sector_size;
84 split_at_seq_end = !job.multifile_segment;
85 workarounds = job.workarounds;
86 max_segment_size = static_cast<off_t>(job.max_segment_size)
87 * static_cast<off_t>(1024 * 1024);
88 max_PTS = static_cast<clockticks>(job.max_PTS) * CLOCKS;
89 video_delay = static_cast<clockticks>(job.video_offset);
90 audio_delay = static_cast<clockticks>(job.audio_offset);
91 switch( mux_format )
92 {
93 case MPEG_FORMAT_VCD :
94 data_rate = 75*2352; /* 75 raw CD sectors/sec */
95 case MPEG_FORMAT_VCD_NSR : /* VCD format, non-standard rate */
96 mjpeg_info( "Selecting VCD output profile");
97 video_buffers_iframe_only = false;
98 mpeg = 1;
99 packets_per_pack = 1;
100 sys_header_in_pack1 = 0;
101 always_sys_header_in_pack = 0;
102 sector_transport_size = 2352; /* Each 2352 bytes with 2324 bytes payload */
103 transport_prefix_sectors = 30;
104 sector_size = 2324;
105 buffers_in_video = 1;
106 always_buffers_in_video = 0;
107 buffers_in_audio = 1; // This is needed as otherwise we have
108 always_buffers_in_audio = 1; // to stuff the packer header which
109 // must be 13 bytes for VCD audio
110 vcd_zero_stuffing = 20; // The famous 20 zero bytes for VCD
111 // audio sectors.
112 dtspts_for_all_vau = false;
113 sector_align_iframeAUs = false;
114 timestamp_iframe_only = false;
115 seg_starts_with_video = true;
116 if( job.video_tracks == 0 )
117 {
118 mjpeg_info( "Audio-only VCD track - variable-bit-rate (VCD2.0)");
119 vbr = true;
120 }
121 break;
122
123 case MPEG_FORMAT_MPEG2 :
124 mjpeg_info( "Selecting generic MPEG2 output profile");
125 mpeg = 2;
126 packets_per_pack = 1;
127 sys_header_in_pack1 = 1;
128 always_sys_header_in_pack = 0;
129 sector_transport_size = 2048; /* Each 2352 bytes with 2324 bytes payload */
130 transport_prefix_sectors = 0;
131 sector_size = 2048;
132 buffers_in_video = 1;
133 always_buffers_in_video = 0;
134 buffers_in_audio = 1;
135 always_buffers_in_audio = 1;
136 vcd_zero_stuffing = 0;
137 vbr = true;
138 dtspts_for_all_vau = 0;
139 timestamp_iframe_only = false;
140 video_buffers_iframe_only = false;
141 break;
142
143 case MPEG_FORMAT_SVCD :
144 data_rate = 150*2324;
145
146 case MPEG_FORMAT_SVCD_NSR : /* Non-standard data-rate */
147 mjpeg_info( "Selecting SVCD output profile");
148 mpeg = 2;
149 packets_per_pack = 1;
150 sys_header_in_pack1 = 0;
151 always_sys_header_in_pack = 0;
152 sector_transport_size = 2324;
153 transport_prefix_sectors = 0;
154 sector_size = 2324;
155 vbr = true;
156 buffers_in_video = 1;
157 always_buffers_in_video = 0;
158 buffers_in_audio = 1;
159 always_buffers_in_audio = 0;
160 vcd_zero_stuffing = 0;
161 dtspts_for_all_vau = 0;
162 sector_align_iframeAUs = true;
163 seg_starts_with_video = true;
164 timestamp_iframe_only = false;
165 video_buffers_iframe_only = false;
166 break;
167
168 case MPEG_FORMAT_VCD_STILL :
169 data_rate = 75*2352; /* 75 raw CD sectors/sec */
170 vbr = false;
171 mpeg = 1;
172 split_at_seq_end = false;
173 packets_per_pack = 1;
174 sys_header_in_pack1 = 0;
175 always_sys_header_in_pack = 0;
176 sector_transport_size = 2352; /* Each 2352 bytes with 2324 bytes payload */
177 transport_prefix_sectors = 0;
178 sector_size = 2324;
179 buffers_in_video = 1;
180 always_buffers_in_video = 0;
181 buffers_in_audio = 1;
182 always_buffers_in_audio = 0;
183 vcd_zero_stuffing = 20;
184 dtspts_for_all_vau = 1;
185 sector_align_iframeAUs = true;
186 timestamp_iframe_only = false;
187 video_buffers_iframe_only = false;
188 break;
189
190 case MPEG_FORMAT_SVCD_STILL :
191 mjpeg_info( "Selecting SVCD output profile");
192 if( data_rate == 0 )
193 data_rate = 150*2324;
194 mpeg = 2;
195 packets_per_pack = 1;
196 sys_header_in_pack1 = 0;
197 always_sys_header_in_pack = 0;
198 sector_transport_size = 2324;
199 transport_prefix_sectors = 0;
200 sector_size = 2324;
201 vbr = true;
202 buffers_in_video = 1;
203 always_buffers_in_video = 0;
204 buffers_in_audio = 1;
205 always_buffers_in_audio = 0;
206 vcd_zero_stuffing = 0;
207 dtspts_for_all_vau = 0;
208 sector_align_iframeAUs = true;
209 timestamp_iframe_only = false;
210 video_buffers_iframe_only = false;
211 break;
212
213 case MPEG_FORMAT_DVD :
214 mjpeg_info( "Selecting generic DVD output profile (PROVISIONAL)");
215 if( data_rate == 0 )
216 data_rate = 1260000;
217 mpeg = 2;
218 packets_per_pack = 1;
219 sys_header_in_pack1 = false; // Handle by control packets
220 always_sys_header_in_pack = false;
221 sector_transport_size = 2048;
222 transport_prefix_sectors = 0;
223 sector_size = 2048;
224 buffers_in_video = true;
225 always_buffers_in_video = false;
226 buffers_in_audio = true;
227 always_buffers_in_audio = false;
228 vcd_zero_stuffing = 0;
229 dtspts_for_all_vau = 0;
230 sector_align_iframeAUs = true;
231 timestamp_iframe_only = true;
232 video_buffers_iframe_only = true;
233 vbr = true;
234 break;
235
236 case MPEG_FORMAT_DVD_NAV :
237 mjpeg_info( "Selecting dvdauthor DVD output profile");
238 if( data_rate == 0 )
239 data_rate = 1260000;
240 mpeg = 2;
241 packets_per_pack = 1;
242 sys_header_in_pack1 = false; // Handle by control packets
243 always_sys_header_in_pack = false;
244 sector_transport_size = 2048;
245 transport_prefix_sectors = 0;
246 sector_size = 2048;
247 buffers_in_video = true;
248 always_buffers_in_video = false;
249 buffers_in_audio = true;
250 always_buffers_in_audio = false;
251 vcd_zero_stuffing = 0;
252 dtspts_for_all_vau = 0;
253 sector_align_iframeAUs = true;
254 timestamp_iframe_only = true;
255 video_buffers_iframe_only = true;
256 vbr = true;
257 seg_starts_with_video = true; // Needs special NAV sector 1st!
258 break;
259
260 default : /* MPEG_FORMAT_MPEG1 - auto format MPEG1 */
261 mjpeg_info( "Selecting generic MPEG1 output profile");
262 //mpeg = 1;
263 sys_header_in_pack1 = 1;
264 transport_prefix_sectors = 0;
265 buffers_in_video = 1;
266 always_buffers_in_video = 1;
267 buffers_in_audio = 0;
268 always_buffers_in_audio = 1;
269 vcd_zero_stuffing = 0;
270 dtspts_for_all_vau = 0;
271 sector_align_iframeAUs = false;
272 timestamp_iframe_only = false;
273 video_buffers_iframe_only = false;
274 break;
275 }
276 }
277
278 /**************************************
279 *
280 * Initialise the elementary stream readers / output sector formatter
281 * objects for the various kinds of input stream.
282 *
283 *************************************/
284
InitInputStreams(MultiplexJob & job)285 void Multiplexor::InitInputStreams(MultiplexJob &job)
286 {
287 //
288 // S(VCD) Stills are sufficiently unusual to require their own
289 // special initialisation
290 //
291 if( MPEG_STILLS_FORMAT(job.mux_format) )
292 InitInputStreamsForStills( job );
293 else
294 InitInputStreamsForVideo( job );
295 }
296
InitInputStreamsForStills(MultiplexJob & job)297 void Multiplexor::InitInputStreamsForStills(MultiplexJob & job )
298 {
299 std::vector<VideoParams *>::iterator vidparm = job.video_param.begin();
300 unsigned int frame_interval;
301 unsigned int i;
302 vector<JobStream *> video_strms;
303 job.GetInputStreams( video_strms, MPEG_VIDEO );
304 vector<JobStream *> mpa_strms;
305 job.GetInputStreams( mpa_strms, MPEG_AUDIO );
306
307 switch( job.mux_format )
308 {
309 case MPEG_FORMAT_VCD_STILL :
310 mjpeg_info( "Multiplexing VCD stills: %d stills streams.", video_strms.size() );
311 {
312 frame_interval = 30; // 30 Frame periods
313 if( mpa_strms.size() > 0 && video_strms.size() > 2 )
314 mjpeg_error_exit1("VCD stills: no more than two streams (one normal one hi-res) possible");
315
316
317 VCDStillsStream *str[2];
318
319 for( i = 0; i< video_strms.size(); ++i )
320 {
321 FrameIntervals *ints =
322 new ConstantFrameIntervals( frame_interval );
323 str[i] =
324 new VCDStillsStream( *(video_strms[i]->bs),
325 new StillsParams( *vidparm, ints),
326 *this );
327 estreams.push_back( str[i] );
328 vstreams.push_back( str[i] );
329 str[i]->Init();
330 ++vidparm;
331 }
332 if( video_strms.size() == 2 )
333 {
334 str[0]->SetSibling(str[1]);
335 str[1]->SetSibling(str[0]);
336 }
337 }
338 break;
339 case MPEG_FORMAT_SVCD_STILL :
340 mjpeg_info( "Multiplexing SVCD stills: %d stills streams %d audio streams", video_strms.size(), mpa_strms.size() );
341 frame_interval = 30;
342 if( video_strms.size() > 1 )
343 {
344 mjpeg_error_exit1("SVCD stills streams may only contain a single video stream");
345 }
346 else if( video_strms.size() > 0 )
347 {
348 ConstantFrameIntervals *intervals;
349 StillsStream *str;
350 intervals = new ConstantFrameIntervals( frame_interval );
351 str = new StillsStream( *(video_strms[0]->bs),
352 new StillsParams( *vidparm, intervals ),
353 *this );
354 estreams.push_back( str );
355 vstreams.push_back( str );
356 str->Init();
357 }
358 for( i = 0 ; i < mpa_strms.size() ; ++i )
359 {
360 AudioStream *audioStrm = new MPAStream( *(mpa_strms[i]->bs), *this);
361 audioStrm->Init ( i);
362 estreams.push_back(audioStrm);
363 astreams.push_back(audioStrm);
364 }
365 break;
366 default:
367 mjpeg_error_exit1("Only VCD and SVCD stills format for the moment...");
368 }
369
370 }
371
InitInputStreamsForVideo(MultiplexJob & job)372 void Multiplexor::InitInputStreamsForVideo(MultiplexJob & job )
373 {
374 mjpeg_info( "Multiplexing video program stream!" );
375
376 unsigned int audio_track = 0;
377 unsigned int video_track = 0;
378 std::vector<VideoParams *>::iterator vidparm = job.video_param.begin();
379 std::vector<LpcmParams *>::iterator lpcmparm = job.lpcm_param.begin();
380
381
382 std::vector<JobStream *>::iterator i;
383 for( i = job.streams.begin() ; i < job.streams.end() ; ++i )
384 {
385 switch( (*i)->kind )
386 {
387
388 case MPEG_VIDEO :
389 {
390 VideoStream *videoStrm;
391 //
392 // The first video stream is made the master stream...
393 //
394 if( video_track == 0 && job.mux_format == MPEG_FORMAT_DVD_NAV )
395 videoStrm = new DVDVideoStream( *(*i)->bs,
396 *vidparm,
397 *this);
398 else
399 videoStrm = new VideoStream( *(*i)->bs,
400 *vidparm,
401 *this);
402 videoStrm->Init( video_track );
403 ++video_track;
404 ++vidparm;
405 estreams.push_back( videoStrm );
406 vstreams.push_back( videoStrm );
407 }
408 break;
409 case MPEG_AUDIO :
410 {
411 AudioStream *audioStrm = new MPAStream( *(*i)->bs, *this);
412 audioStrm->Init ( audio_track );
413 estreams.push_back(audioStrm);
414 astreams.push_back(audioStrm);
415 ++audio_track;
416 }
417 break;
418 case AC3_AUDIO :
419 {
420 AudioStream *audioStrm = new AC3Stream( *(*i)->bs, *this);
421 audioStrm->Init ( audio_track );
422 estreams.push_back(audioStrm);
423 astreams.push_back(audioStrm);
424 ++audio_track;
425 }
426 break;
427 case DTS_AUDIO :
428 {
429 AudioStream *audioStrm = new DTSStream( *(*i)->bs, *this);
430 audioStrm->Init ( audio_track );
431 estreams.push_back(audioStrm);
432 astreams.push_back(audioStrm);
433 ++audio_track;
434 }
435 break;
436 case LPCM_AUDIO :
437 {
438 AudioStream *audioStrm = new LPCMStream( *(*i)->bs, *lpcmparm, *this);
439 audioStrm->Init ( audio_track );
440 estreams.push_back(audioStrm);
441 astreams.push_back(audioStrm);
442 ++lpcmparm;
443 ++audio_track;
444 }
445 break;
446 #ifdef ZALPHA
447 // just copies the video parameters from the first video stream
448 case Z_ALPHA :
449 {
450 ZAlphaStream *zalphaStrm = new ZAlphaStream( *(*i)->bs, *(job.video_param.begin()), *this);
451 zalphaStrm->Init (0);
452 estreams.push_back(zalphaStrm);
453 vstreams.push_back(zalphaStrm);
454 //++vidparm;
455 }
456 #endif
457 }
458 }
459 }
460
461
462 /*******************************************************************
463 Find the timecode corresponding to given position in the system stream
464 (assuming the SCR starts at 0 at the beginning of the stream
465 @param bytepos byte position in the stream
466 @param ts returns the number of clockticks the bytepos is from the file start
467 ****************************************************************** */
468
ByteposTimecode(bitcount_t bytepos,clockticks & ts)469 void Multiplexor::ByteposTimecode(bitcount_t bytepos, clockticks &ts)
470 {
471 ts = (bytepos*CLOCKS)/static_cast<bitcount_t>(dmux_rate);
472 }
473
474
475 /**********
476 *
477 * NextPosAndSCR - Update nominal (may be >= actual) byte count
478 * and SCR to next output sector.
479 *
480 ********/
481
NextPosAndSCR()482 void Multiplexor::NextPosAndSCR()
483 {
484 bytes_output += sector_transport_size;
485 ByteposTimecode( bytes_output, current_SCR );
486 if (start_of_new_pack)
487 {
488 psstrm->CreatePack (&pack_header, current_SCR, mux_rate);
489 pack_header_ptr = &pack_header;
490 if( include_sys_header )
491 sys_header_ptr = &sys_header;
492 else
493 sys_header_ptr = NULL;
494
495 }
496 else
497 pack_header_ptr = NULL;
498 }
499
500
501 /**********
502 *
503 * SetPosAndSCR - Update nominal (may be >= actual) byte count
504 * and SCR to next output sector.
505 * @param bytepos byte position in the stream
506 ********/
507
SetPosAndSCR(bitcount_t bytepos)508 void Multiplexor::SetPosAndSCR( bitcount_t bytepos )
509 {
510 bytes_output = bytepos;
511 ByteposTimecode( bytes_output, current_SCR );
512 if (start_of_new_pack)
513 {
514 psstrm->CreatePack (&pack_header, current_SCR, mux_rate);
515 pack_header_ptr = &pack_header;
516 if( include_sys_header )
517 sys_header_ptr = &sys_header;
518 else
519 sys_header_ptr = NULL;
520
521 }
522 else
523 pack_header_ptr = NULL;
524 }
525
526 /*
527 Stream syntax parameters.
528 */
529
530
531
532
533
534 typedef enum { start_segment, mid_segment,
535 runout_segment }
536 segment_state;
537
538
539 /**
540 * Compute the number of run-in sectors needed to fill up the buffers to
541 * suit the type of stream being muxed.
542 *
543 * For stills we have to ensure an entire buffer is loaded as we only
544 * ever process one frame at a time.
545 * @returns the number of run-in sectors needed to fill up the buffers to suit the type of stream being muxed.
546 */
547
RunInSectors()548 unsigned int Multiplexor::RunInSectors()
549 {
550 std::vector<ElementaryStream *>::iterator str;
551 unsigned int sectors_delay = 1;
552
553 for( str = vstreams.begin(); str < vstreams.end(); ++str )
554 {
555
556 if( MPEG_STILLS_FORMAT( mux_format ) )
557 {
558 sectors_delay += static_cast<unsigned int>(1.02*(*str)->BufferSize()) / sector_size+2;
559 }
560 else if( vbr )
561 sectors_delay += 3*(*str)->BufferSize() / ( 4 * sector_size );
562 else
563 sectors_delay += 5 *(*str)->BufferSize() / ( 6 * sector_size );
564 }
565 sectors_delay += astreams.size();
566 return sectors_delay;
567 }
568
569 /**********************************************************************
570 *
571 * Initializes the output stream proper. Traverses the input files
572 * and calculates their payloads. Estimates the multiplex
573 * rate. Estimates the necessary stream delay for the different
574 * substreams.
575 *
576 *********************************************************************/
577
578
Init()579 void Multiplexor::Init()
580 {
581 std::vector<ElementaryStream *>::iterator str;
582 clockticks delay;
583 unsigned int sectors_delay;
584
585 Pack_struc dummy_pack;
586 Sys_header_struc dummy_sys_header;
587 Sys_header_struc *sys_hdr;
588 unsigned int nominal_rate_sum;
589
590 mjpeg_info("SYSTEMS/PROGRAM stream:");
591 psstrm->Open();
592
593 /* These are used to make (conservative) decisions
594 about whether a packet should fit into the recieve buffers...
595 Audio packets always have PTS fields, video packets needn'.
596 TODO: Really this should be encapsulated in Elementary stream...?
597 */
598 psstrm->CreatePack (&dummy_pack, 0, mux_rate);
599 if( always_sys_header_in_pack )
600 {
601 vector<MuxStream *> muxstreams;
602 AppendMuxStreamsOf( estreams, muxstreams );
603 psstrm->CreateSysHeader (&dummy_sys_header, mux_rate,
604 !vbr, 1, true, true, muxstreams);
605 sys_hdr = &dummy_sys_header;
606 }
607 else
608 sys_hdr = NULL;
609
610 nominal_rate_sum = 0;
611 for( str = estreams.begin(); str < estreams.end(); ++str )
612 {
613 switch( (*str)->Kind() )
614 {
615 case ElementaryStream::audio :
616 (*str)->SetMaxPacketData(
617 psstrm->PacketPayload( **str, NULL, NULL,
618 false, true, false )
619 );
620 (*str)->SetMinPacketData(
621 psstrm->PacketPayload( **str, sys_hdr, &dummy_pack,
622 always_buffers_in_audio, true, false )
623 );
624
625 break;
626 case ElementaryStream::video :
627 (*str)->SetMaxPacketData(
628 psstrm->PacketPayload( **str, NULL, NULL,
629 false, false, false )
630 );
631 (*str)->SetMinPacketData(
632 psstrm->PacketPayload( **str, sys_hdr, &dummy_pack,
633 always_buffers_in_video, true, true )
634 );
635 break;
636 default :
637 mjpeg_error_exit1("INTERNAL: Only audio and video payload calculations implemented!");
638
639 }
640
641 if( (*str)->NominalBitRate() == 0 && data_rate == 0)
642 mjpeg_error_exit1( "Variable bit-rate stream present: output stream (max) data-rate *must* be specified!");
643 nominal_rate_sum += (*str)->NominalBitRate();
644 }
645
646 /* Attempt to guess a sensible mux rate for the given video and *
647 audio estreams. This is a rough and ready guess for MPEG-1 like
648 formats. */
649
650
651 dmux_rate = static_cast<int>(1.0205 * nominal_rate_sum);
652 dmux_rate = (dmux_rate/50 + 25)*50/8;
653
654 mjpeg_info ("rough-guess multiplexed stream data rate : %07d", dmux_rate*8 );
655 if( data_rate != 0 )
656 mjpeg_info ("target data-rate specified : %7d", data_rate*8 );
657
658 if( data_rate == 0 )
659 {
660 mjpeg_info( "Setting best-guess data rate.");
661 }
662 else if ( data_rate >= dmux_rate)
663 {
664 mjpeg_info( "Setting specified specified data rate: %7d", data_rate*8 );
665 dmux_rate = data_rate;
666 }
667 else if ( data_rate < dmux_rate )
668 {
669 mjpeg_warn( "Target data rate lower than computed requirement!");
670 mjpeg_warn( "N.b. a 20%% or so discrepancy in variable bit-rate");
671 mjpeg_warn( "streams is common and harmless provided no time-outs will occur");
672 dmux_rate = data_rate;
673 }
674
675 mux_rate = dmux_rate/50;
676
677
678 //
679 // Now that all mux parameters are set we can trigger parsing
680 // of actual input stream data and calculation of associated
681 // PTS/DTS by causing the read of the first AU's...
682 //
683 for( str = estreams.begin(); str < estreams.end(); ++str )
684 {
685 (*str)->NextAU();
686 }
687
688 //
689 // Now that we have both output and input streams initialised and
690 // data-rates set we can make a decent job of setting the maximum
691 // STD buffer delay in video streams.
692 //
693
694 for( str = vstreams.begin(); str < vstreams.end(); ++str )
695 {
696 static_cast<VideoStream*>(*str)->SetMaxStdBufferDelay( dmux_rate );
697 }
698
699 /* To avoid Buffer underflow, the DTS of the first video and audio AU's
700 must be offset sufficiently forward of the SCR to allow the buffer
701 time to fill before decoding starts. Calculate the necessary delays...
702 */
703
704 sectors_delay = RunInSectors();
705
706 ByteposTimecode(
707 static_cast<bitcount_t>(sectors_delay*sector_transport_size),
708 delay );
709 video_delay += delay;
710 audio_delay += delay;
711
712 /*
713 * The PTS of the first frame may be different from its DTS.
714 * Thus to hit perfect A/V sync we need to delay audio by the difference
715 * PTS-DTS.
716 *
717 */
718
719 if( vstreams.size() != 0 )
720 {
721 audio_delay += vstreams[0]->BasePTS()-vstreams[0]->BaseDTS();
722 }
723
724 mjpeg_info( "Run-in Sectors = %d Video delay = %lld Audio delay = %lld",
725 sectors_delay,
726 video_delay / 300,
727 audio_delay / 300 );
728
729 if( max_PTS != 0 )
730
731 mjpeg_info( "Multiplexed stream will be ended at %lld seconds playback time\n", max_PTS/CLOCKS );
732
733 }
734
735 /**
736 Prints the current status of the substreams.
737 @param level the desired log level
738 */
MuxStatus(log_level_t level)739 void Multiplexor::MuxStatus(log_level_t level)
740 {
741 std::vector<ElementaryStream *>::iterator str;
742 for( str = estreams.begin(); str < estreams.end(); ++str )
743 {
744 switch( (*str)->Kind() )
745 {
746 case ElementaryStream::video :
747 mjpeg_log( level,
748 "Video %02x: buf=%7d frame=%06d sector=%08d",
749 (*str)->stream_id,
750 (*str)->BufferSize()-(*str)->bufmodel.Space(),
751 (*str)->DecodeOrder(),
752 (*str)->nsec
753 );
754 break;
755 case ElementaryStream::audio :
756 mjpeg_log( level,
757 "Audio %02x: buf=%7d frame=%06d sector=%08d",
758 (*str)->stream_id,
759 (*str)->BufferSize()-(*str)->bufmodel.Space(),
760 (*str)->DecodeOrder(),
761 (*str)->nsec
762 );
763 break;
764 default :
765 mjpeg_log( level,
766 "Other %02x: buf=%7d sector=%08d",
767 (*str)->stream_id,
768 (*str)->bufmodel.Space(),
769 (*str)->nsec
770 );
771 break;
772 }
773 }
774 if( !vbr )
775 mjpeg_log( level,
776 "Padding : sector=%08d",
777 pstrm.nsec
778 );
779
780
781 }
782
783
784 /**
785 Append input substreams to the output multiplex stream.
786 */
AppendMuxStreamsOf(vector<ElementaryStream * > & elem,vector<MuxStream * > & mux)787 void Multiplexor::AppendMuxStreamsOf( vector<ElementaryStream *> &elem,
788 vector<MuxStream *> &mux )
789 {
790 std::vector<ElementaryStream *>::iterator str;
791 for( str = elem.begin(); str < elem.end(); ++str )
792 {
793 mux.push_back( static_cast<MuxStream *>( *str ) );
794 }
795 }
796
797 /******************************************************************
798 Program start-up packets. Generate any irregular packets
799 needed at the start of the stream...
800 Note: *must* leave a sensible in-stream system header in
801 sys_header.
802 TODO: get rid of this grotty sys_header global.
803 ******************************************************************/
OutputPrefix()804 void Multiplexor::OutputPrefix( )
805 {
806 vector<MuxStream *> vmux,amux,emux;
807 AppendMuxStreamsOf( vstreams, vmux );
808 AppendMuxStreamsOf( astreams, amux );
809 AppendMuxStreamsOf( estreams, emux );
810
811 /* Deal with transport padding */
812 SetPosAndSCR( bytes_output +
813 transport_prefix_sectors*sector_transport_size );
814
815 /* VCD: Two padding packets with video and audio system headers */
816
817 switch (mux_format)
818 {
819 case MPEG_FORMAT_VCD :
820 case MPEG_FORMAT_VCD_NSR :
821
822 /* Annoyingly VCD generates seperate system headers for
823 audio and video ... DOH... */
824 if( astreams.size() > 1 || vstreams.size() > 1 ||
825 astreams.size() + vstreams.size() != estreams.size() )
826 {
827 mjpeg_error_exit1("VCD man only have max. 1 audio and 1 video stream");
828 }
829
830 if( vstreams.size() > 0 )
831 {
832 /* First packet carries video-info-only sys_header */
833 psstrm->CreateSysHeader (&sys_header, mux_rate,
834 false, true,
835 true, true, vmux );
836 sys_header_ptr = &sys_header;
837 pack_header_ptr = &pack_header;
838 OutputPadding( false);
839 }
840
841 if( astreams.size() > 0 )
842 {
843
844 /* Second packet carries audio-info-only sys_header */
845 psstrm->CreateSysHeader (&sys_header, mux_rate,
846 false, true,
847 true, true, amux );
848 sys_header_ptr = &sys_header;
849 pack_header_ptr = &pack_header;
850 OutputPadding( true );
851 }
852 break;
853
854 case MPEG_FORMAT_SVCD :
855 case MPEG_FORMAT_SVCD_NSR :
856 /* First packet carries sys_header */
857 psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, true,
858 true, true, emux );
859 sys_header_ptr = &sys_header;
860 pack_header_ptr = &pack_header;
861 OutputPadding(false);
862 break;
863
864 case MPEG_FORMAT_VCD_STILL :
865 /* First packet carries small-still sys_header */
866 /* TODO No support mixed-mode stills sequences... */
867 psstrm->CreateSysHeader (&sys_header, mux_rate, false, false,
868 true, true, emux );
869 sys_header_ptr = &sys_header;
870 pack_header_ptr = &pack_header;
871 OutputPadding( false);
872 break;
873
874 case MPEG_FORMAT_SVCD_STILL :
875 /* TODO: Video only at present */
876 /* First packet carries video-info-only sys_header */
877 psstrm->CreateSysHeader (&sys_header, mux_rate,
878 false, true,
879 true, true, vmux );
880 sys_header_ptr = &sys_header;
881 pack_header_ptr = &pack_header;
882 OutputPadding( false);
883 break;
884
885 case MPEG_FORMAT_DVD_NAV :
886 /* A DVD System header is a weird thing. We seem to need to
887 include buffer info about streams 0xb8, 0xb9, 0xbd, 0xbf even if
888 they're not physically present but the buffers for the actual
889 video streams aren't included.
890 */
891 {
892 // MANY DVD streams appear not to include system headers
893 // and some tools have weak parsers that can't handle all
894 // the possible variations. Soooo probably best not to generate
895 // them
896 DummyMuxStream dvd_0xb9_strm_dummy( 0xb9, 1, 232*1024 );
897 DummyMuxStream dvd_0xb8_strm_dummy( 0xb8, 0, 4096 );
898 DummyMuxStream dvd_0xbf_strm_dummy( 0xbf, 1, 2048 );
899 vector<MuxStream *> dvdmux;
900 std::vector<MuxStream *>::iterator muxstr;
901 dvdmux.push_back( &dvd_0xb9_strm_dummy );
902 dvdmux.push_back( &dvd_0xb8_strm_dummy );
903 unsigned int max_priv1_buffer = 58*1024;
904 for( muxstr = amux.begin(); muxstr < amux.end(); ++muxstr )
905 {
906 // We mux *many* substreams on PRIVATE_STR_1
907 // we set the system header buffer size to the maximum
908 // of all those we find
909 if( (*muxstr)->stream_id == PRIVATE_STR_1 )
910 {
911 if( (*muxstr)->BufferSize() > max_priv1_buffer )
912 max_priv1_buffer = (*muxstr)->BufferSize();
913 }
914 // Now the *sane* thing to do if MPEG audio is present would be
915 // record this in the system header. However, dvdauthor lacks
916 // a header parser and barfs if the system headers aren't exactly
917 // 18 bytes. Soooo we simply skip them for now...
918 // TOOD: Add back in when dvdauthor can parse system headers
919 //else
920 // dvdmux.push_back( *muxstr );
921 }
922
923 DummyMuxStream dvd_priv1_strm_dummy( PRIVATE_STR_1, 1,
924 max_priv1_buffer );
925 dvdmux.push_back( &dvd_priv1_strm_dummy );
926
927 dvdmux.push_back( &dvd_0xbf_strm_dummy );
928 psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, false,
929 true, true, dvdmux );
930 sys_header_ptr = &sys_header;
931 pack_header_ptr = &pack_header;
932 /* It is then followed up by a pair of PRIVATE_STR_2 packets which
933 we keep empty 'cos we don't know what goes there...
934 */
935 }
936 break;
937
938 default :
939 /* Create the in-stream header in case it is needed */
940 psstrm->CreateSysHeader (&sys_header, mux_rate, !vbr, false,
941 true, true, emux );
942
943
944 }
945
946
947
948 }
949
950
951
952 /******************************************************************
953 Program shutdown packets. Generate any irregular packets
954 needed at the end of the stream...
955
956 ******************************************************************/
957
OutputSuffix()958 void Multiplexor::OutputSuffix()
959 {
960 psstrm->CreatePack (&pack_header, current_SCR, mux_rate);
961 psstrm->CreateSector (&pack_header, NULL,
962 0,
963 pstrm,
964 false,
965 true,
966 0, 0,
967 TIMESTAMPBITS_NO );
968 }
969
970 /******************************************************************
971
972 Main multiplex iteration.
973 Opens and closes all needed files and manages the correct
974 call od the respective Video- and Audio- packet routines.
975 The basic multiplexing is done here. Buffer capacity and
976 Timestamp checking is also done here, decision is taken
977 wether we should genereate a Video-, Audio- or Padding-
978 packet.
979 ******************************************************************/
980
981
982
Multiplex()983 void Multiplexor::Multiplex()
984
985 {
986 segment_state seg_state;
987 std::vector<bool> completed;
988 std::vector<bool>::iterator pcomp;
989 std::vector<ElementaryStream *>::iterator str;
990
991 unsigned int packets_left_in_pack = 0; /* Suppress warning */
992 bool padding_packet;
993 bool video_first = true;
994
995 Init( );
996
997 unsigned int i;
998 for(i = 0; i < estreams.size() ; ++i )
999 completed.push_back(false);
1000
1001
1002 /* Let's try to read in unit after unit and to write it out into
1003 the outputstream. The only difficulty herein lies into the
1004 buffer management, and into the fact the the actual access
1005 unit *has* to arrive in time, that means the whole unit
1006 (better yet, packet data), has to arrive before arrival of
1007 DTS. If both buffers are full we'll generate a padding packet
1008
1009 Of course, when we start we're starting a new segment with no
1010 bytes output...
1011 */
1012
1013 ByteposTimecode( sector_transport_size, ticks_per_sector );
1014 seg_state = start_segment;
1015 running_out = false;
1016 for(;;)
1017 {
1018 bool completion = true;
1019
1020 for( str = estreams.begin(); str < estreams.end() ; ++str )
1021 completion &= (*str)->MuxCompleted();
1022 if( completion )
1023 break;
1024
1025 /* A little state-machine for handling the transition from one
1026 segment to the next
1027 */
1028 bool runout_incomplete;
1029 VideoStream *master;
1030 switch( seg_state )
1031 {
1032
1033 /* Audio and slave video access units at end of segment.
1034 If there are any audio AU's whose PTS implies they
1035 should be played *before* the video AU starting the
1036 next segement is presented we mux them out. Once
1037 they're gone we've finished this segment so we write
1038 the suffix switch file, and start muxing a new segment.
1039 */
1040 case runout_segment :
1041 runout_incomplete = false;
1042 for( str = estreams.begin(); str < estreams.end(); ++str )
1043 {
1044 runout_incomplete |= !(*str)->RunOutComplete();
1045 }
1046
1047 if( runout_incomplete )
1048 break;
1049
1050 /* Otherwise we write the stream suffix and start a new
1051 stream file */
1052 OutputSuffix();
1053 psstrm->NextSegment();
1054
1055 running_out = false;
1056 seg_state = start_segment;
1057
1058 /* Starting a new segment.
1059 We send the segment prefix, video and audio reciever
1060 buffers are assumed to start empty. We reset the segment
1061 length count and hence the SCR.
1062
1063 */
1064
1065 case start_segment :
1066 mjpeg_info( "New sequence commences..." );
1067 SetPosAndSCR(0);
1068 MuxStatus( LOG_INFO );
1069
1070 for( str = estreams.begin(); str < estreams.end(); ++str )
1071 {
1072 (*str)->AllDemuxed();
1073 }
1074
1075 packets_left_in_pack = packets_per_pack;
1076 start_of_new_pack = true;
1077 include_sys_header = sys_header_in_pack1;
1078 buffers_in_video = always_buffers_in_video;
1079 video_first = seg_starts_with_video & (vstreams.size() > 0);
1080 OutputPrefix();
1081
1082 /* Set the offset applied to the raw PTS/DTS of AU's to
1083 make the DTS of the first AU in the master (video) stream
1084 precisely the video delay plus whatever time we wasted in
1085 the sequence pre-amble.
1086
1087 The DTS of the remaining streams are set so that
1088 (modulo the relevant delay offset) they maintain the
1089 same relative timing to the master stream.
1090
1091 */
1092
1093 clockticks ZeroSCR;
1094
1095 if( vstreams.size() != 0 )
1096 ZeroSCR = vstreams[0]->BaseDTS();
1097 else
1098 ZeroSCR = estreams[0]->BaseDTS();
1099
1100 for( str = vstreams.begin(); str < vstreams.end(); ++str )
1101 (*str)->SetSyncOffset(video_delay + current_SCR - ZeroSCR );
1102 for( str = astreams.begin(); str < astreams.end(); ++str )
1103 (*str)->SetSyncOffset(audio_delay + current_SCR - ZeroSCR );
1104 pstrm.nsec = 0;
1105 for( str = estreams.begin(); str < estreams.end(); ++str )
1106 (*str)->nsec = 0;
1107 seg_state = mid_segment;
1108 break;
1109
1110 case mid_segment :
1111 /* Once we exceed our file size limit, we need to
1112 start a new file soon. If we want a single stream we
1113 simply switch.
1114
1115 Otherwise we're in the last gop of the current segment
1116 (and need to start running streams out ready for a
1117 clean continuation in the next segment).
1118 TODO: runout_PTS really needs to be expressed in
1119 sync delay adjusted units...
1120 */
1121
1122 master =
1123 vstreams.size() > 0 ?
1124 static_cast<VideoStream*>(vstreams[0]) : 0 ;
1125 if( psstrm->SegmentLimReached() )
1126 {
1127 if( split_at_seq_end )
1128 mjpeg_warn( "File size exceeded before split-point in video stream" );
1129 mjpeg_info( "Starting new output file...");
1130 psstrm->NextSegment();
1131 }
1132 else if( master != 0 && master->SeqEndRunOut() )
1133 {
1134 const AUnit *nextIframe = master->NextIFrame();
1135 if( split_at_seq_end && nextIframe != 0)
1136 {
1137 runout_PTS = master->RequiredPTS(nextIframe);
1138 mjpeg_info( "Sequence end marker! Running out...");
1139 mjpeg_info("Run out PTS limit to AU %d %lld SCR=%lld",
1140 nextIframe->dorder,
1141 runout_PTS/300,
1142 current_SCR/300 );
1143 MuxStatus( LOG_INFO );
1144 running_out = true;
1145 seg_state = runout_segment;
1146 }
1147 else
1148 {
1149 mjpeg_warn( "Sequence end without following I-frame!" );
1150 }
1151 }
1152 break;
1153
1154 }
1155
1156 padding_packet = false;
1157 start_of_new_pack = (packets_left_in_pack == packets_per_pack);
1158
1159 for( str = estreams.begin(); str < estreams.end(); ++str )
1160 {
1161 (*str)->DemuxedTo(current_SCR);
1162 }
1163
1164
1165
1166 //
1167 // Find the ready-to-mux stream with the most urgent DTS
1168 //
1169 ElementaryStream *despatch = 0;
1170 clockticks earliest = 0;
1171 for( str = estreams.begin(); str < estreams.end(); ++str )
1172 {
1173 #ifdef STREAM_LOGGING
1174 mjpeg_debug("%02x: SCR=%lld (%.3f) mux=%d %d reqDTS=%lld ",
1175 (*str)->stream_id,
1176 current_SCR,
1177 static_cast<double>(current_SCR) /(90.0*300.0),
1178 (*str)->MuxPossible(current_SCR),
1179 (*str)->BufferSize()-(*str)->bufmodel.Space(),
1180 (*str)->RequiredDTS()/300
1181
1182 );
1183 #endif
1184 if( (*str)->MuxPossible(current_SCR) &&
1185 ( !video_first || (*str)->Kind() == ElementaryStream::video )
1186 )
1187 {
1188 if( despatch == 0 || earliest > (*str)->RequiredDTS() )
1189 {
1190 despatch = *str;
1191 earliest = (*str)->RequiredDTS();
1192 }
1193 }
1194 }
1195
1196 if( underrun_ignore > 0 )
1197 --underrun_ignore;
1198
1199 if( despatch )
1200 {
1201 despatch->BufferAndOutputSector();
1202 video_first = false;
1203 if( current_SCR >= earliest && underrun_ignore == 0)
1204 {
1205 mjpeg_warn( "Stream %02x: data will arrive too late sent(SCR)=%lld required(DTS)=%lld",
1206 despatch->stream_id,
1207 current_SCR/300,
1208 earliest/300 );
1209 MuxStatus( LOG_WARN );
1210 // Give the stream a chance to recover
1211 underrun_ignore = 300;
1212 ++underruns;
1213 if( underruns > 10 )
1214 {
1215 //mjpeg_error_exit1("Too many frame drops -exiting" );
1216 }
1217 }
1218 if( despatch->nsec > 50 &&
1219 despatch->Lookahead( ) != 0 && ! running_out)
1220 despatch->UpdateBufferMinMax();
1221 padding_packet = false;
1222
1223 }
1224 else
1225 {
1226 //
1227 // If we got here no stream could be muxed out.
1228 // We therefore generate padding packets if necessary
1229 // usually this is because reciever buffers are likely to be
1230 // full.
1231 //
1232 if( vbr )
1233 {
1234 //
1235 // VBR: For efficiency we bump SCR up to five times or
1236 // until it looks like buffer status will change
1237 NextPosAndSCR();
1238 clockticks next_change = static_cast<clockticks>(0);
1239 for( str = estreams.begin(); str < estreams.end(); ++str )
1240 {
1241 clockticks change_time = (*str)->bufmodel.NextChange();
1242 if( next_change == 0 || change_time < next_change )
1243 {
1244 next_change = change_time;
1245 }
1246 }
1247
1248 unsigned int bumps = 5;
1249 while( bumps > 0
1250 && next_change > current_SCR + ticks_per_sector)
1251 {
1252 NextPosAndSCR();
1253 --bumps;
1254 }
1255
1256 }
1257 else
1258 {
1259 // Just output a padding packet
1260 OutputPadding ( false);
1261 }
1262 padding_packet = true;
1263 }
1264
1265 /* Update the counter for pack packets. VBR is a tricky
1266 case as here padding packets are "virtual" */
1267
1268 if( ! (vbr && padding_packet) )
1269 {
1270 --packets_left_in_pack;
1271 if (packets_left_in_pack == 0)
1272 packets_left_in_pack = packets_per_pack;
1273 }
1274
1275 MuxStatus( LOG_DEBUG );
1276 /* Unless sys headers are always required we turn them off after the first
1277 packet has been generated */
1278 include_sys_header = always_sys_header_in_pack;
1279
1280 pcomp = completed.begin();
1281 str = estreams.begin();
1282 while( str < estreams.end() )
1283 {
1284 if( !(*pcomp) && (*str)->MuxCompleted() )
1285 {
1286 mjpeg_info( "STREAM %02x completed @ frame %d.", (*str)->stream_id, (*str)->DecodeOrder() );
1287 MuxStatus( LOG_DEBUG );
1288 (*pcomp) = true;
1289 }
1290 ++str;
1291 ++pcomp;
1292 }
1293 }
1294 // Tidy up
1295
1296 OutputSuffix( );
1297 psstrm->Close();
1298 mjpeg_info( "Multiplex completion at SCR=%lld.", current_SCR/300);
1299 MuxStatus( LOG_INFO );
1300 for( str = estreams.begin(); str < estreams.end(); ++str )
1301 {
1302 (*str)->Close();
1303 if( (*str)->nsec <= 50 )
1304 mjpeg_info( "BUFFERING stream too short for useful statistics");
1305 else
1306 mjpeg_info( "BUFFERING min %d Buf max %d",
1307 (*str)->BufferMin(),
1308 (*str)->BufferMax()
1309 );
1310 }
1311
1312 if( underruns> 0 )
1313 {
1314 mjpeg_info( "MUX STATUS: Frame data under-runs detected!" ); // MEANX was exit
1315 }
1316 else
1317 {
1318 mjpeg_info( "MUX STATUS: no under-runs detected.");
1319 }
1320 }
1321
1322 /**
1323 Calculate the packet payload of the output stream at a certain timestamp.
1324 @param strm the output stream
1325 @param buffers the number of buffers
1326 @param PTSstamp presentation time stamp
1327 @param DTSstamp decoding time stamp
1328 */
PacketPayload(MuxStream & strm,bool buffers,bool PTSstamp,bool DTSstamp)1329 unsigned int Multiplexor::PacketPayload( MuxStream &strm, bool buffers,
1330 bool PTSstamp, bool DTSstamp )
1331 {
1332 return psstrm->PacketPayload( strm, sys_header_ptr, pack_header_ptr,
1333 buffers,
1334 PTSstamp, DTSstamp)
1335 - strm.StreamHeaderSize();
1336 }
1337
1338 /***************************************************
1339
1340 WritePacket - Write out a normal packet carrying data from one of
1341 the elementary stream being muxed.
1342 @param max_packet_data_size the maximum packet data size allowed
1343 @param strm output mux stream
1344 @param buffers ?
1345 @param PTSstamp presentation time stamp of the packet
1346 @param DTSstamp decoding time stamp of the packet
1347 @param timestamps ?
1348 @param returns the written bytes/packets (?)
1349 ***************************************************/
1350
1351 unsigned int
WritePacket(unsigned int max_packet_data_size,MuxStream & strm,bool buffers,clockticks PTS,clockticks DTS,uint8_t timestamps)1352 Multiplexor::WritePacket( unsigned int max_packet_data_size,
1353 MuxStream &strm,
1354 bool buffers,
1355 clockticks PTS,
1356 clockticks DTS,
1357 uint8_t timestamps
1358 )
1359 {
1360 unsigned int written =
1361 psstrm->CreateSector ( pack_header_ptr,
1362 sys_header_ptr,
1363 max_packet_data_size,
1364 strm,
1365 buffers,
1366 false,
1367 PTS,
1368 DTS,
1369 timestamps );
1370 NextPosAndSCR();
1371 return written;
1372 }
1373
1374 /***************************************************
1375 *
1376 * WriteRawSector - Write out a packet carrying data for
1377 * a control packet with irregular content.
1378 @param rawsector data for the raw sector
1379 @param length length of the raw sector
1380 ***************************************************/
1381
1382 void
WriteRawSector(uint8_t * rawsector,unsigned int length)1383 Multiplexor::WriteRawSector( uint8_t *rawsector,
1384 unsigned int length
1385 )
1386 {
1387 //
1388 // Writing raw sectors when packs stretch over multiple sectors
1389 // is a recipe for disaster!
1390 //
1391 assert( packets_per_pack == 1 );
1392 psstrm->RawWrite( rawsector, length );
1393 NextPosAndSCR();
1394
1395 }
1396
1397
1398
1399 /******************************************************************
1400 OutputPadding
1401
1402 generates Pack/Sys Header/Packet information for a
1403 padding stream and saves the sector
1404
1405 We have to pass in a special flag to cope with appalling mess VCD
1406 makes of audio packets (the last 20 bytes being dropped thing) 0 =
1407 Fill the packet completetely. This include "audio packets" that
1408 include no actual audio, only a system header and padding.
1409 @param vcd_audio_pad flag for VCD audio padding
1410 ******************************************************************/
1411
1412
OutputPadding(bool vcd_audio_pad)1413 void Multiplexor::OutputPadding (bool vcd_audio_pad)
1414
1415 {
1416 if( vcd_audio_pad )
1417 psstrm->CreateSector ( pack_header_ptr, sys_header_ptr,
1418 0,
1419 vcdapstrm,
1420 false, false,
1421 0, 0,
1422 TIMESTAMPBITS_NO );
1423 else
1424 psstrm->CreateSector ( pack_header_ptr, sys_header_ptr,
1425 0,
1426 pstrm,
1427 false, false,
1428 0, 0,
1429 TIMESTAMPBITS_NO );
1430 ++pstrm.nsec;
1431 NextPosAndSCR();
1432
1433 }
1434
1435 /******************************************************************
1436 * OutputGOPControlSector
1437 * DVD System headers are carried in peculiar sectors carrying 2
1438 * PrivateStream2 packets. We're sticking 0's in the packets
1439 * as we have no idea what's supposed to be in there.
1440 *
1441 * Thanks to Brent Byeler who worked out this work-around.
1442 *
1443 ******************************************************************/
1444
OutputDVDPriv2()1445 void Multiplexor::OutputDVDPriv2 ( )
1446 {
1447 uint8_t *packet_size_field;
1448 uint8_t *index;
1449 uint8_t *sector_buf = new uint8_t[sector_size];
1450 unsigned int tozero;
1451 assert( sector_size == 2048 );
1452 PS_Stream::BufferSectorHeader( sector_buf,
1453 pack_header_ptr,
1454 &sys_header,
1455 index );
1456 PS_Stream::BufferPacketHeader( index,
1457 PRIVATE_STR_2,
1458 2, // MPEG 2
1459 false, // No buffers
1460 0,
1461 0,
1462 0, // No timestamps
1463 0,
1464 TIMESTAMPBITS_NO,
1465 0, // Natural PES header length
1466 packet_size_field,
1467 index );
1468 tozero = sector_buf+1024-index;
1469 memset( index, 0, tozero);
1470 index += tozero;
1471 PS_Stream::BufferPacketSize( packet_size_field, index );
1472
1473 PS_Stream::BufferPacketHeader( index,
1474 PRIVATE_STR_2,
1475 2, // MPEG 2
1476 false, // No buffers
1477 0,
1478 0,
1479 0, // No timestamps
1480 0,
1481 TIMESTAMPBITS_NO,
1482 0, // Natural PES header length
1483 packet_size_field,
1484 index );
1485 tozero = sector_buf+2048-index;
1486 memset( index, 0, tozero );
1487 index += tozero;
1488 PS_Stream::BufferPacketSize( packet_size_field, index );
1489
1490 WriteRawSector( sector_buf, sector_size );
1491
1492 delete [] sector_buf;
1493 }
1494
1495
1496 /*
1497 * Local variables:
1498 * c-file-style: "stroustrup"
1499 * tab-width: 4
1500 * indent-tabs-mode: nil
1501 * End:
1502 */
1503