Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / bdwrite.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2016-2020 William Morrow
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published
7  * by the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20
21 //#include "bd.h"
22 //This program was created by inverting libbluray, without any docs,
23 //  so it is probably got problems.  Still, works on my Samsung player.
24 //  thanks to: Petri Hintukainen, William Hahne, John Stebbinsm, et.al.
25 //
26 //Usage:
27 // ./bd <tgt_dir_path> <playlist-0> <sep> <playlistp1> <sep> ... <sep> <playlist-n>
28 //    <sep> == -<pgm_pid> | --<pgm_pid> | ---<pgm_pid>
29 //    <pgm_pid> may be empty string, or a numeric pgm_pid for curr title clip
30 //    <pgm_pid> defaults to first pgm probed.
31 //    <playlist-x> == <clip-0.m2ts> <clip-1.m2ts> ... <clip-n.m2ts>
32 // eg:
33 // ./brwrite /tmp/dir /path/menu.m2ts --- /path/clip0.m2ts /path/clip1.m2ts -- /path/clip2.m2ts
34 //
35 // one title is built for each playlist
36 // playlist-0 is used as first-play item
37 //
38 // the basic idea is to use playlist-0 as a menu / directions to
39 // use the bluray player remote-control to select the desired title
40 // and start the play, avoiding the need for a menu system.
41 //
42 // if the first play item is the main title, that is ok also.
43 // ./brwrite /tmp/dir /path/title.m2ts
44 //
45 //
46 //To use a bluray bd-re rewriteable: (such as for /dev/sr1)
47 // dvd+rw-format /dev/sr1  (only done once to init the media)
48 // mkudffs /dev/sr1 $((`cat /sys/block/sr1/size`*512/2048-1))
49 // mount /dev/sr1 /mnt1
50 // cp -av <tgd_dir_path>/BDMV /mnt1/.
51 // umount /mnt1
52 // eject sr1
53 //
54 #ifndef __BD_H__
55 #define __BD_H__
56 #include <stdio.h>
57 #include <unistd.h>
58 #include <stdint.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #if !defined (__FreeBSD__)
62 #include <endian.h>
63 #else
64 #include <sys/endian.h>
65 #endif
66 #include <limits.h>
67 #include <sys/stat.h>
68 // work arounds (centos)
69 #ifndef INT64_MAX
70 #define INT64_MAX 9223372036854775807LL
71 #endif
72 #ifndef INT64_MIN
73 #define INT64_MIN (-INT64_MAX-1)
74 #endif
75
76 #include "arraylist.h"
77 #include "cstrdup.h"
78 #define BCTEXTLEN 1024
79 #define BLURAY_TS_PKTSZ 192L
80
81 static const int bd_sig = 2;
82
83 extern "C" {
84 #include "libavfilter/buffersrc.h"
85 #include "libavfilter/buffersink.h"
86 #include "libavformat/avformat.h"
87 #include "libavformat/avio.h"
88 #include "libavcodec/avcodec.h"
89 #include "libavfilter/avfilter.h"
90 #include "libavutil/avutil.h"
91 #include "libavutil/opt.h"
92 #include "libavutil/pixdesc.h"
93 #include "libswresample/swresample.h"
94 #include "libswscale/swscale.h"
95 }
96
97 class stream;
98
99 enum {
100   obj_hdmv = 1,
101   obj_bdj = 2,
102   title_len = 20,
103   pb_typ_movie = 0,
104   pb_typ_iactv = 1,
105   pb_len = 16,
106
107   BLURAY_APP_TYPE_MAIN_MOVIE = 1,
108   BLURAY_APP_TYPE_MAIN_TIMED_SLIDE_SHOW = 2,
109   BLURAY_APP_TYPE_MAIN_BROWSED_SLIDE_SHOW = 3,
110   BLURAY_APP_TYPE_SUBPATH_BROWSED_SLIDE_SHOW = 4,
111   BLURAY_APP_TYPE_SUBPATH_IG_MENU = 5,
112   BLURAY_APP_TYPE_SUBPATH_TEXT_SUBTITLE = 6,
113   BLURAY_APP_TYPE_SUBPATH_ELEMENTARY_STREAM = 7,
114
115   BLURAY_STREAM_TYPE_VIDEO_MPEG1 = 0x01,
116   BLURAY_STREAM_TYPE_VIDEO_MPEG2 = 0x02,
117   BLURAY_STREAM_TYPE_AUDIO_MPEG1 = 0x03,
118   BLURAY_STREAM_TYPE_AUDIO_MPEG2 = 0x04,
119   BLURAY_STREAM_TYPE_AUDIO_LPCM = 0x80,
120   BLURAY_STREAM_TYPE_AUDIO_AC3 = 0x81,
121   BLURAY_STREAM_TYPE_AUDIO_DTS = 0x82,
122   BLURAY_STREAM_TYPE_AUDIO_TRUHD = 0x83,
123   BLURAY_STREAM_TYPE_AUDIO_AC3PLUS = 0x84,
124   BLURAY_STREAM_TYPE_AUDIO_DTSHD = 0x85,
125   BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER = 0x86,
126   BLURAY_STREAM_TYPE_VIDEO_VC1 = 0xea,
127   BLURAY_STREAM_TYPE_VIDEO_H264 = 0x1b,
128   BLURAY_STREAM_TYPE_VIDEO_H264_MVC = 0x20,
129   BLURAY_STREAM_TYPE_VIDEO_HEVC = 0x24,
130   BLURAY_STREAM_TYPE_SUB_PG = 0x90,
131   BLURAY_STREAM_TYPE_SUB_IG = 0x91,
132   BLURAY_STREAM_TYPE_SUB_TEXT = 0x92,
133   BLURAY_STREAM_TYPE_AUDIO_AC3PLUS_SECONDARY = 0xa1,
134   BLURAY_STREAM_TYPE_AUDIO_DTSHD_SECONDARY = 0xa2,
135
136   BLURAY_MARK_TYPE_ENTRY = 0x01,
137   BLURAY_MARK_TYPE_LINK  = 0x02,
138
139   BLURAY_PLAYBACK_TYPE_SEQUENTIAL = 1,
140   BLURAY_PLAYBACK_TYPE_RANDOM = 2,
141   BLURAY_PLAYBACK_TYPE_SHUFFLE = 3,
142
143   BLURAY_VIDEO_FORMAT_480I = 1,  // ITU-R BT.601-5
144   BLURAY_VIDEO_FORMAT_576I = 2,  // ITU-R BT.601-4
145   BLURAY_VIDEO_FORMAT_480P = 3,  // SMPTE 293M
146   BLURAY_VIDEO_FORMAT_1080I = 4, // SMPTE 274M
147   BLURAY_VIDEO_FORMAT_720P = 5,  // SMPTE 296M
148   BLURAY_VIDEO_FORMAT_1080P = 6, // SMPTE 274M
149   BLURAY_VIDEO_FORMAT_576P = 7,  // ITU-R BT.1358
150   BLURAY_VIDEO_FORMAT_2160P = 8,
151
152   BLURAY_VIDEO_RATE_24000_1001 = 1, // 23.976
153   BLURAY_VIDEO_RATE_24 = 2,
154   BLURAY_VIDEO_RATE_25 = 3,
155   BLURAY_VIDEO_RATE_30000_1001 = 4, // 29.97
156   BLURAY_VIDEO_RATE_50 = 6,
157   BLURAY_VIDEO_RATE_60000_1001 = 7, // 59.94
158
159   BLURAY_ASPECT_RATIO_4_3 = 2,
160   BLURAY_ASPECT_RATIO_16_9 = 3,
161
162   BLURAY_AUDIO_FORMAT_MONO = 1,
163   BLURAY_AUDIO_FORMAT_STEREO = 3,
164   BLURAY_AUDIO_FORMAT_MULTI_CHAN = 6,
165   BLURAY_AUDIO_FORMAT_COMBO = 12,   // Stereo ac3/dts,
166
167   BLURAY_AUDIO_RATE_48 = 1,
168   BLURAY_AUDIO_RATE_96 = 4,
169   BLURAY_AUDIO_RATE_192 = 5,
170   BLURAY_AUDIO_RATE_192_COMBO = 12, // 48 or 96 ac3/dts, 192 mpl/dts-hd
171   BLURAY_AUDIO_RATE_96_COMBO = 14,  // 48 ac3/dts, 96 mpl/dts-hd
172   BLURAY_TEXT_CHAR_CODE_UTF8 = 0x01,
173   BLURAY_TEXT_CHAR_CODE_UTF16BE = 0x02,
174   BLURAY_TEXT_CHAR_CODE_SHIFT_JIS = 0x03,
175   BLURAY_TEXT_CHAR_CODE_EUC_KR = 0x04,
176   BLURAY_TEXT_CHAR_CODE_GB18030_20001 = 0x05,
177   BLURAY_TEXT_CHAR_CODE_CN_GB = 0x06,
178   BLURAY_TEXT_CHAR_CODE_BIG5 = 0x07,
179
180   BLURAY_STILL_NONE = 0x00,
181   BLURAY_STILL_TIME = 0x01,
182   BLURAY_STILL_INFINITE = 0x02,
183
184   BLURAY_PG_TEXTST_STREAM = 0x01,
185   BLURAY_SECONDARY_VIDEO_STREAM = 0x02,
186   BLURAY_SECONDARY_AUDIO_STREAM = 0x03,
187 };
188
189 class bs_file {
190   FILE *fp;
191   uint32_t reg, len;
192   int64_t fpos, fsz;
193 public:
194   bs_file() { fp = 0; }
195   ~bs_file() {}
196
197   void init();
198   int  open(const char *fn);
199   void close();
200   void write(uint32_t v, int n);
201   void pad(int n);
202   void padb(int n) { pad(n*8); }
203   int64_t posb() { return fpos; }
204   void posb(int64_t n);
205   int64_t pos() { return posb()*8 + len; }
206   void writeb(uint8_t * bp, int n);
207   void writeb(const char *cp, int n) {
208     writeb((uint8_t *) cp, n);
209   }
210 };
211
212 class bs_length {
213   int64_t fpos, len;
214 public:
215   bs_length() { fpos = len = 0; }
216   int64_t bs_posb(bs_file &bs) { return bs.posb() - fpos; }
217   void bs_len(bs_file &bs, int n) {
218     bs.write(len, n);  fpos = bs.posb();
219   }
220   void bs_end(bs_file &bs) {
221     len = bs_posb(bs);
222   }
223   void bs_ofs(bs_file &bs, int n) {
224     bs.write(fpos-n/8, n);
225   }
226   void bs_zofs(bs_file &bs, int n) {
227     bs.write(!len ? 0 : fpos-n/8, n);
228   }
229 };
230
231 class _bd_stream_info {
232 public:
233   uint8_t coding_type;
234   uint8_t format;
235   uint8_t rate;
236   uint8_t char_code;
237   uint8_t lang[4];
238   uint16_t pid;
239   uint8_t aspect;
240   uint8_t subpath_id;
241
242   _bd_stream_info() { memset(this, 0, sizeof(*this)); }
243   ~_bd_stream_info() {}
244 };
245
246 class bd_stream_info : public _bd_stream_info {
247 public:
248   bd_stream_info() {}
249   ~bd_stream_info() {}
250 };
251
252 class _bd_clip_info {
253 public:
254   uint32_t pkt_count;
255   uint8_t still_mode;
256   uint16_t still_time;          /* seconds */
257   uint64_t start_time;
258   uint64_t in_time;
259   uint64_t out_time;
260
261   _bd_clip_info() { memset(this, 0, sizeof(*this)); }
262   ~_bd_clip_info() {}
263 };
264
265 class bd_clip_info : public _bd_clip_info {
266 public:
267   ArrayList<bd_stream_info *> video_streams;
268   ArrayList<bd_stream_info *> audio_streams;
269   ArrayList<bd_stream_info *> pg_streams;
270   ArrayList<bd_stream_info *> ig_streams;
271   ArrayList<bd_stream_info *> sec_audio_streams;
272   ArrayList<bd_stream_info *> sec_video_streams;
273
274   bd_clip_info() {}
275   ~bd_clip_info() {
276     video_streams.remove_all_objects();
277     audio_streams.remove_all_objects();
278     pg_streams.remove_all_objects();
279     ig_streams.remove_all_objects();
280     sec_audio_streams.remove_all_objects();
281     sec_video_streams.remove_all_objects();
282   }
283 };
284
285 class _bd_title_chapter {
286 public:
287   uint32_t idx;
288   uint64_t start;
289   uint64_t duration;
290   uint64_t offset;
291   unsigned clip_ref;
292
293   _bd_title_chapter() { memset(this, 0, sizeof(*this)); }
294   ~_bd_title_chapter() {}
295 };
296
297 class bd_title_chapter : public _bd_title_chapter {
298 public:
299   bd_title_chapter() {}
300   ~bd_title_chapter() {}
301 };
302
303 class _bd_title_mark {
304 public:
305   uint32_t idx;
306   int type;
307   uint64_t start;
308   uint64_t duration;
309   uint64_t offset;
310   unsigned clip_ref;
311
312   _bd_title_mark() { memset(this, 0, sizeof(*this)); }
313   ~_bd_title_mark() {}
314 };
315
316 class bd_title_mark : public _bd_title_mark {
317 public:
318   bd_title_mark() {}
319   ~bd_title_mark() {}
320 };
321
322 class _bd_title_info {
323 public:
324   uint32_t idx;
325   uint32_t playlist;
326   uint64_t duration;
327   uint8_t angle_count;
328
329   _bd_title_info() { memset(this, 0, sizeof(*this)); }
330   ~_bd_title_info() {}
331 };
332
333 class bd_title_info : public _bd_title_info {
334 public:
335   ArrayList<bd_clip_info *> clips;
336   ArrayList<bd_title_chapter *> chapters;
337   ArrayList<bd_title_mark *> marks;
338
339   bd_title_info() {}
340   ~bd_title_info() {
341     clips.remove_all_objects();
342     chapters.remove_all_objects();
343     marks.remove_all_objects();
344   }
345 };
346
347 class _clpi_stc_seq {
348 public:
349   uint16_t pcr_pid;
350   uint32_t spn_stc_start;
351   uint32_t presentation_start_time;
352   uint32_t presentation_end_time;
353
354   _clpi_stc_seq() { memset(this, 0, sizeof(*this)); }
355   ~_clpi_stc_seq() {}
356 };
357
358 class clpi_stc_seq : public _clpi_stc_seq {
359 public:
360   int write();
361
362   clpi_stc_seq() {}
363   ~clpi_stc_seq() {}
364 };
365
366 class _clpi_atc_seq {
367 public:
368   uint32_t spn_atc_start;
369   uint8_t offset_stc_id;
370
371   _clpi_atc_seq() { memset(this, 0, sizeof(*this)); }
372   ~_clpi_atc_seq() {}
373 };
374
375 class clpi_atc_seq : public _clpi_atc_seq {
376 public:
377   ArrayList<clpi_stc_seq *> stc_seq;
378   int write();
379
380   clpi_atc_seq() {}
381   ~clpi_atc_seq() {
382     stc_seq.remove_all_objects();
383   }
384 };
385
386 class clpi_sequences : public bs_length,
387                         public ArrayList<clpi_atc_seq *> {
388 public:
389   int write();
390
391   clpi_sequences() {}
392   ~clpi_sequences() { remove_all_objects(); }
393 };
394
395 class _clpi_ts_type {
396 public:
397   uint8_t validity;
398   char format_id[5];
399
400   _clpi_ts_type() { memset(this, 0, sizeof(*this)); }
401   ~_clpi_ts_type() {}
402 };
403
404 class clpi_ts_type : public _clpi_ts_type {
405 public:
406   clpi_ts_type() {}
407   ~clpi_ts_type() {}
408 };
409
410 class _clpi_atc_delta {
411 public:
412   uint32_t delta;
413   char file_id[6];
414   char file_code[5];
415
416   _clpi_atc_delta() { memset(this, 0, sizeof(*this)); }
417   ~_clpi_atc_delta() {}
418 };
419
420 class clpi_atc_delta : public _clpi_atc_delta {
421 public:
422   int write();
423
424   clpi_atc_delta() {}
425   ~clpi_atc_delta() {}
426 };
427
428 class _clpi_font {
429 public:
430   char file_id[6];
431
432   _clpi_font() { memset(this, 0, sizeof(*this)); }
433   ~_clpi_font() {}
434 };
435
436 class clpi_font : public _clpi_font {
437 public:
438   clpi_font() {}
439   ~clpi_font() {}
440 };
441
442 class clpi_font_info {
443 public:
444   ArrayList<clpi_font *> font;
445
446   clpi_font_info() {}
447   ~clpi_font_info() {
448     font.remove_all_objects();
449   }
450 };
451
452 class _clpi_clip_info {
453 public:
454   uint8_t clip_stream_type;
455   uint8_t application_type;
456   uint8_t is_atc_delta;
457   uint32_t ts_recording_rate;
458   uint32_t num_source_packets;
459
460   _clpi_clip_info() { memset(this, 0, sizeof(*this)); }
461   ~_clpi_clip_info() {}
462 };
463
464 class clpi_clip_info : public bs_length, public _clpi_clip_info {
465 public:
466   clpi_ts_type ts_type_info;
467   clpi_font_info font_info;
468   ArrayList<clpi_atc_delta *> atc_delta;
469   int write();
470
471   clpi_clip_info() {}
472   ~clpi_clip_info() {
473     atc_delta.remove_all_objects();
474   }
475 };
476
477 class _clpi_prog_stream {
478 public:
479   uint16_t pid;
480   uint8_t coding_type;
481   uint8_t format;
482   uint8_t rate;
483   uint8_t aspect;
484   uint8_t oc_flag;
485   uint8_t char_code;
486   char lang[4];
487
488   _clpi_prog_stream() { memset(this, 0, sizeof(*this)); }
489   ~_clpi_prog_stream() {}
490 };
491
492 class clpi_prog_stream : public bs_length, public _clpi_prog_stream {
493 public:
494   int write();
495
496   clpi_prog_stream() {}
497   ~clpi_prog_stream() {}
498 };
499
500 class _clpi_ep_coarse {
501 public:
502   int ref_ep_fine_id;
503   int pts_ep;
504   uint32_t spn_ep;
505
506   _clpi_ep_coarse() { memset(this, 0, sizeof(*this)); }
507   ~_clpi_ep_coarse() {}
508 };
509
510 class clpi_ep_coarse : public _clpi_ep_coarse {
511 public:
512   int write();
513
514   clpi_ep_coarse() {}
515   ~clpi_ep_coarse() {}
516 };
517
518 class _clpi_ep_fine {
519 public:
520   uint8_t is_angle_change_point;
521   uint8_t i_end_position_offset;
522   int pts_ep;
523   int spn_ep;
524
525   _clpi_ep_fine() { memset(this, 0, sizeof(*this)); }
526   ~_clpi_ep_fine() {}
527 };
528
529 class clpi_ep_fine : public _clpi_ep_fine {
530 public:
531   int write();
532
533   clpi_ep_fine() {}
534   ~clpi_ep_fine() {}
535 };
536
537 class _clpi_ep_map_entry {
538 public:
539   uint8_t ep_stream_type;
540   uint32_t ep_map_stream_start_addr;
541
542   _clpi_ep_map_entry() { memset(this, 0, sizeof(*this)); }
543   ~_clpi_ep_map_entry() {}
544 };
545
546 class clpi_ep_map_entry : public _clpi_ep_map_entry {
547 public:
548   uint32_t fine_start;
549   uint16_t pid;
550   ArrayList<clpi_ep_coarse *> coarse;
551   ArrayList<clpi_ep_fine *> fine;
552   int write(uint32_t ep_map_pos);
553   int write_map();
554
555   clpi_ep_map_entry(int id) { fine_start = 0;  pid = id; }
556   ~clpi_ep_map_entry() {
557     coarse.remove_all_objects();
558     fine.remove_all_objects();
559   }
560 };
561
562 class _clpi_prog {
563 public:
564   uint32_t spn_program_sequence_start;
565   uint8_t num_groups;
566   _clpi_prog() { memset(this, 0, sizeof(*this)); }
567   ~_clpi_prog() {}
568 };
569
570 class clpi_prog : public _clpi_prog {
571 public:
572   ArrayList<clpi_prog_stream *> streams;
573   uint16_t program_map_pid;
574
575   int write();
576   clpi_prog(int pmt_pid) { program_map_pid = pmt_pid; }
577   ~clpi_prog() { streams.remove_all_objects(); }
578 };
579
580 class clpi_programs : public bs_length,
581                         public ArrayList<clpi_prog *> {
582 public:
583   int write();
584
585   clpi_programs() {}
586   ~clpi_programs() { remove_all_objects(); }
587 };
588
589 class clpi_extents : public bs_length,
590                         public ArrayList<uint32_t> {
591 public:
592   int write();
593
594   clpi_extents() {}
595   ~clpi_extents() {}
596 };
597 class _clpi_cpi {
598 public:
599   uint8_t type;
600
601   _clpi_cpi() { type = 0; }
602   ~_clpi_cpi() {}
603 };
604
605 class clpi_cpi : public bs_length, public _clpi_cpi,
606                         public ArrayList<clpi_ep_map_entry *> {
607 public:
608   int write();
609
610   clpi_cpi() {}
611   ~clpi_cpi() { remove_all_objects(); }
612 };
613
614 class clpi_cmrk : public bs_length {
615 public:
616   int write();
617
618   clpi_cmrk() {}
619   ~clpi_cmrk() {}
620 };
621
622
623 class bd_uo_mask {
624 public:
625   unsigned int menu_call : 1;
626   unsigned int title_search : 1;
627   unsigned int chapter_search : 1;
628   unsigned int time_search : 1;
629   unsigned int skip_to_next_point : 1;
630   unsigned int skip_to_prev_point : 1;
631   unsigned int play_firstplay : 1;
632   unsigned int stop : 1;
633   unsigned int pause_on : 1;
634   unsigned int pause_off : 1;
635   unsigned int still_off : 1;
636   unsigned int forward : 1;
637   unsigned int backward : 1;
638   unsigned int resume : 1;
639   unsigned int move_up : 1;
640   unsigned int move_down : 1;
641   unsigned int move_left : 1;
642   unsigned int move_right : 1;
643   unsigned int select : 1;
644   unsigned int activate : 1;
645   unsigned int select_and_activate : 1;
646   unsigned int primary_audio_change : 1;
647   unsigned int reserved0 : 1;
648   unsigned int angle_change : 1;
649   unsigned int popup_on : 1;
650   unsigned int popup_off : 1;
651   unsigned int pg_enable_disable : 1;
652   unsigned int pg_change : 1;
653   unsigned int secondary_video_enable_disable : 1;
654   unsigned int secondary_video_change : 1;
655   unsigned int secondary_audio_enable_disable : 1;
656   unsigned int secondary_audio_change : 1;
657   unsigned int reserved1 : 1;
658   unsigned int pip_pg_change : 1;
659
660   int write();
661   bd_uo_mask() {
662     memset(this, 0, sizeof(*this));
663   }
664   ~bd_uo_mask() {
665   }
666 };
667
668 class _mpls_stream {
669 public:
670   uint8_t stream_type;
671   uint8_t coding_type;
672   uint16_t pid;
673   uint8_t subpath_id;
674   uint8_t subclip_id;
675   uint8_t format;
676   uint8_t rate;
677   uint8_t dynamic_range_type;
678   uint8_t color_space;
679   uint8_t cr_flag;
680   uint8_t hdr_plus_flag;
681   uint8_t char_code;
682   char lang[4];
683
684   _mpls_stream() { memset(this, 0, sizeof(*this)); }
685   ~_mpls_stream() {}
686 };
687
688 class mpls_stream : public _mpls_stream {
689 public:
690   bs_length strm, code;
691   int write();
692
693   mpls_stream() {}
694   ~mpls_stream() {}
695 };
696
697 class _mpls_stn {
698 public:
699   uint8_t num_pip_pg;
700   _mpls_stn() {
701     num_pip_pg = 0;
702   }
703   ~_mpls_stn() {}
704 };
705
706 class mpls_stn : public bs_length, public _mpls_stn {
707 public:
708   ArrayList<mpls_stream *> video;
709   ArrayList<mpls_stream *> audio;
710   ArrayList<mpls_stream *> pg;
711   ArrayList<mpls_stream *> ig;
712   ArrayList<mpls_stream *> secondary_audio;
713   ArrayList<mpls_stream *> secondary_video;
714   // Secondary audio specific fields
715   ArrayList<uint8_t> sa_primary_audio_ref;
716   // Secondary video specific fields
717   ArrayList<uint8_t> sv_secondary_audio_ref;
718   ArrayList<uint8_t> sv_pip_pg_ref;
719
720   int write();
721   mpls_stn() {}
722   ~mpls_stn() {
723     video.remove_all_objects();
724     audio.remove_all_objects();
725     pg.remove_all_objects();
726     ig.remove_all_objects();
727     secondary_audio.remove_all_objects();
728     secondary_video.remove_all_objects();
729   }
730 };
731
732 class _mpls_clip {
733 public:
734   char clip_id[6];
735   char codec_id[5];
736   uint8_t stc_id;
737
738   _mpls_clip() { memset(this, 0, sizeof(*this)); }
739   ~_mpls_clip() {}
740 };
741
742 class mpls_clip : public _mpls_clip {
743 public:
744   mpls_clip() { strcpy(codec_id, "M2TS"); }
745   ~mpls_clip() {}
746 };
747
748 class _mpls_pi {
749 public:
750   uint8_t is_multi_angle;
751   uint8_t connection_condition;
752   uint32_t in_time;
753   uint32_t out_time;
754   uint8_t random_access_flag;
755   uint8_t still_mode;
756   uint16_t still_time;
757   uint8_t is_different_audio;
758   uint8_t is_seamless_angle;
759
760   _mpls_pi() { memset(this, 0, sizeof(*this)); }
761   ~_mpls_pi() {}
762 };
763
764 class mpls_pi : public bs_length, public _mpls_pi {
765 public:
766   bd_uo_mask uo_mask;
767   ArrayList<mpls_clip *> clip;
768   mpls_stn stn;
769
770   int write();
771
772   mpls_pi() {}
773   ~mpls_pi() {
774     clip.remove_all_objects();
775   }
776 };
777
778 class _mpls_plm {
779 public:
780   uint8_t mark_id;
781   uint8_t mark_type;
782   uint16_t play_item_ref;
783   uint32_t time;
784   uint16_t entry_es_pid;
785   uint32_t duration;
786
787   _mpls_plm() { memset(this, 0, sizeof(*this)); }
788   ~_mpls_plm() {}
789 };
790
791 class mpls_plm : public _mpls_plm {
792 public:
793   int write();
794
795   mpls_plm() {}
796   ~mpls_plm() {}
797 };
798
799 class _mpls_ai {
800 public:
801   uint8_t playback_type;
802   uint16_t playback_count;
803   uint8_t random_access_flag;
804   uint8_t audio_mix_flag;
805   uint8_t lossless_bypass_flag;
806
807   _mpls_ai() { memset(this, 0, sizeof(*this)); }
808   ~_mpls_ai() {}
809 };
810
811 class mpls_ai : public bs_length, public _mpls_ai {
812 public:
813   bd_uo_mask uo_mask;
814   int write();
815
816   mpls_ai() {}
817   ~mpls_ai() {}
818 };
819
820 class _mpls_sub_pi {
821 public:
822   uint8_t connection_condition;
823   uint8_t is_multi_clip;
824   uint32_t in_time;
825   uint32_t out_time;
826   uint16_t sync_play_item_id;
827   uint32_t sync_pts;
828
829   _mpls_sub_pi() { memset(this, 0, sizeof(*this)); }
830   ~_mpls_sub_pi() {}
831 };
832
833 class mpls_sub_pi : public bs_length, public _mpls_sub_pi {
834 public:
835   ArrayList<mpls_clip *> clip;
836   int write();
837
838   mpls_sub_pi() {}
839   ~mpls_sub_pi() {
840     clip.remove_all_objects();
841   }
842 };
843
844 class _mpls_sub {
845 public:
846   uint8_t type;
847   uint8_t is_repeat;
848
849   _mpls_sub() { memset(this, 0, sizeof(*this)); }
850   ~_mpls_sub() {}
851 };
852
853 class mpls_sub : public bs_length, public _mpls_sub {
854 public:
855   ArrayList<mpls_sub_pi *> sub_play_item;
856
857   int write();
858   mpls_sub() {}
859   ~mpls_sub() {
860    sub_play_item.remove_all_objects();
861   }
862 };
863
864 class _mpls_pip_data {
865 public:
866   uint32_t time;
867   uint16_t xpos;
868   uint16_t ypos;
869   uint8_t scale_factor;
870
871   _mpls_pip_data() { memset(this, 0, sizeof(*this)); }
872   ~_mpls_pip_data() {}
873 };
874
875 class mpls_pip_data : public _mpls_pip_data {
876 public:
877   int write();
878
879   mpls_pip_data() {}
880   ~mpls_pip_data() {}
881 };
882
883 class _mpls_pip_metadata {
884 public:
885   uint16_t clip_ref;
886   uint8_t secondary_video_ref;
887   uint8_t timeline_type;
888   uint8_t luma_key_flag;
889   uint8_t upper_limit_luma_key;
890   uint8_t trick_play_flag;
891
892   _mpls_pip_metadata() { memset(this, 0, sizeof(*this)); }
893   ~_mpls_pip_metadata() {}
894 };
895
896 class mpls_pip_metadata : public _mpls_pip_metadata {
897 public:
898   ArrayList<mpls_pip_data *> data;
899
900   int write(uint32_t start_address);
901   mpls_pip_metadata() {}
902   ~mpls_pip_metadata() {
903     data.remove_all_objects();
904   }
905 };
906
907 class _mpls_pl {
908 public:
909   uint32_t list_pos;
910   uint32_t mark_pos;
911   uint32_t ext_pos;
912
913   _mpls_pl() { memset(this, 0, sizeof(*this)); }
914   ~_mpls_pl() {}
915 };
916
917 class mpls_pl : public _mpls_pl {
918 public:
919   int sig;
920   bs_length play, mark, subx, pipm;
921   mpls_ai app_info;
922   ArrayList<mpls_pi *> play_item;
923   ArrayList<mpls_sub *> sub_path;
924   ArrayList<mpls_plm *> play_mark;
925   // extension data (profile 5, version 2.4)
926   ArrayList<mpls_sub *> ext_sub_path;
927   // extension data (Picture-In-Picture metadata)
928   ArrayList<mpls_pip_metadata *> ext_pip_data;
929
930   int write_header();
931   int write_playlist();
932   int write_playlistmark();
933   int write_subpath_extension();
934   int write_pip_metadata_extension();
935   int write();
936
937   mpls_pl() { sig = bd_sig; }
938   ~mpls_pl() {
939     play_item.remove_all_objects();
940     sub_path.remove_all_objects();
941     play_mark.remove_all_objects();
942     ext_sub_path.remove_all_objects();
943     ext_pip_data.remove_all_objects();
944   }
945 };
946
947 class _clpi_cl {
948 public:
949   uint32_t sequence_info_start_addr;
950   uint32_t program_info_start_addr;
951   uint32_t cpi_start_addr;
952   uint32_t clip_mark_start_addr;
953   uint32_t ext_data_start_addr;
954
955   _clpi_cl() { memset(this, 0, sizeof(*this)); }
956   ~_clpi_cl() {}
957 };
958
959 class clpi_cl : public _clpi_cl {
960 public:
961   int sig;
962   clpi_clip_info clip;
963   clpi_sequences sequences;
964   clpi_programs programs;
965   clpi_cpi cpi;
966   clpi_extents extents;
967   clpi_programs programs_ss;
968   clpi_cpi cpi_ss;
969   clpi_cmrk cmrk;
970
971   int write_header();
972   int write();
973
974   int write_clpi_extension(int id1, int id2, void *handle);
975   int write_mpls_extension(int id1, int id2, void *handle);
976
977   clpi_cl() { sig = bd_sig; }
978   ~clpi_cl() {}
979 };
980
981 class command_obj {
982 public:
983   union {
984     uint32_t cmd;
985     struct {
986       uint32_t sub_grp:3;       /* command sub-group */
987       uint32_t grp:2;           /* command group */
988       uint32_t op_cnt:3;        /* operand count */
989       uint32_t branch_opt:4;    /* branch option */
990       uint32_t rsvd1:2;
991       uint32_t imm_op2:1;       /* I-flag for operand 2 */
992       uint32_t imm_op1:1;       /* I-flag for operand 1 */
993       uint32_t cmp_opt:4;       /* compare option */
994       uint32_t rsvd2:4;
995       uint32_t set_opt:5;       /* set option */
996       uint32_t rsvd3:3;
997     };
998   };
999   uint32_t dst;
1000   uint32_t src;
1001
1002   command_obj() { cmd = dst = src = 0; }
1003   ~command_obj() {}
1004 };
1005
1006 class _movie_obj {
1007 public:
1008   int resume_intention_flag;
1009   int menu_call_mask;
1010   int title_search_mask;
1011
1012   _movie_obj() { memset(this, 0, sizeof(*this)); }
1013   ~_movie_obj() {}
1014 };
1015
1016 class movie_obj : public _movie_obj {
1017 public:
1018   ArrayList<command_obj *> cmds;
1019
1020   movie_obj() {}
1021   ~movie_obj() {
1022     cmds.remove_all_objects();
1023   }
1024 };
1025
1026 class movie_file : public bs_length {
1027 public:
1028   int sig;
1029   ArrayList<movie_obj *> movies;
1030
1031   movie_file() { sig = bd_sig; }
1032   ~movie_file() {
1033     movies.remove_all_objects();
1034   }
1035
1036   int write();
1037 };
1038
1039 class _pb_obj {
1040 public:
1041   int obj_typ;
1042   int pb_typ;
1043   int hdmv_id;
1044
1045   _pb_obj() { memset(this, 0, sizeof(*this)); }
1046   ~_pb_obj() {}
1047 };
1048
1049 class pb_obj : public _pb_obj {
1050 public:
1051   int last;
1052   char *bdj_name;
1053   void write_obj();
1054
1055   pb_obj() {
1056     last = 0;
1057     bdj_name = 0;
1058   }
1059   ~pb_obj() {
1060     delete [] bdj_name;
1061   }
1062
1063   void set_hdmv(int id, int pt);
1064   void set_bdj(char *nm, int pt);
1065   void write_hdmv_obj(int id_ref);
1066   void write_bdj_obj(char *name);
1067 };
1068
1069 class _title_obj {
1070 public:
1071   int acc_typ;
1072   _title_obj() { acc_typ = 0; }
1073   ~_title_obj() {}
1074 };
1075
1076 class title_obj : public pb_obj, public _title_obj {
1077 public:
1078   title_obj() {}
1079   ~title_obj() {}
1080
1081   void write_obj();
1082 };
1083
1084 class _index_file {
1085 public:
1086   int sig;
1087   int initial_output_mode_preference;
1088   int content_exist_flag;
1089   int video_format;
1090   int frame_rate;
1091
1092   _index_file() { memset(this, 0, sizeof(*this)); }
1093   ~_index_file() {}
1094 };
1095
1096 class index_file : public bs_length, public _index_file {
1097 public:
1098   ArrayList<title_obj *> titles;
1099   pb_obj first_play;
1100   pb_obj top_menu;
1101   char user_data[32];
1102   bs_length exten, appinf;
1103
1104   void write_hdmv_obj(int hdmv_typ, int id_ref);
1105   void write_bdj_obj(int bdj_typ, char *name);
1106   void write_pb_obj(pb_obj * pb);
1107   int write();
1108
1109   index_file() {
1110     sig = bd_sig;
1111     memset(user_data, 0, sizeof(user_data));
1112   }
1113   ~index_file() {
1114     titles.remove_all_objects();
1115   }
1116 };
1117
1118 class _bdid {
1119 public:
1120   uint32_t data_start;
1121   uint32_t extension_data_start;
1122   char org_id[4];
1123   char disc_id[16];
1124
1125   _bdid() { memset(this, 0, sizeof(*this)); }
1126   ~_bdid() {}
1127 };
1128
1129 class bdid : public _bdid {
1130 public:
1131   int sig;
1132   int write();
1133
1134   bdid() { sig = bd_sig; }
1135   ~bdid() {}
1136 };
1137
1138 class stream : public bd_stream_info {
1139 public:
1140   int av_idx;
1141   AVMediaType type;
1142   AVCodecID codec_id;
1143   AVCodecContext *ctx;
1144   int64_t start_pts;
1145   int64_t end_pts;
1146   int64_t last_pts;
1147   int64_t duration;
1148
1149   stream(AVMediaType ty, int i) {
1150     type = ty;  av_idx = i;  ctx = 0;
1151     start_pts = INT64_MAX; end_pts = INT64_MIN;
1152     last_pts = -1;
1153   }
1154   ~stream() { if( ctx ) avcodec_free_context(&ctx); }
1155 };
1156
1157 class mark {
1158 public:
1159   static int cmpr(mark **, mark **);
1160   int64_t sample, pos, pts;
1161   uint32_t pkt, pid;
1162   mark(int64_t s, int64_t p, int64_t ts, uint32_t pk, int id) {
1163     sample = s;  pos = p;  pts = ts; pkt = pk;  pid = id;
1164   }
1165 };
1166
1167 int mark::cmpr(mark **a, mark **b)
1168 {
1169   mark *ap = *(mark **)a,  *bp = *(mark **)b;
1170   return ap->pts > bp->pts ? 1 : ap->pts < bp->pts ? -1 : 0;
1171 }
1172
1173 class _program {
1174 public:
1175   int pmt_pid, pcr_pid, ep_pid;
1176   int64_t start_time, end_time;
1177   int64_t duration;
1178   _program() {
1179     memset(this, 0, sizeof(*this));
1180     start_time = INT64_MAX; end_time = INT64_MIN;
1181   }
1182   ~_program() {}
1183 };
1184
1185 class program : public _program {
1186 public:
1187   int idx;
1188   uint16_t pid;
1189   ArrayList<int> strm_idx;
1190   ArrayList<mark*> marks;
1191   int64_t curr_pos;
1192   int build_toc(clpi_ep_map_entry *map);
1193   void add_label(uint32_t pk, int64_t p, int64_t ts, int id) {
1194     marks.append(new mark(curr_pos, p, ts, pk, id));
1195   }
1196
1197   program(int i, int id) { idx = i;  pid = id;  curr_pos = 0; }
1198   ~program() { marks.remove_all_objects(); }
1199 };
1200
1201 class _media_info {
1202 public:
1203   int bit_rate;
1204   int64_t file_size;
1205
1206   _media_info() {
1207     memset(this, 0, sizeof(*this));
1208   }
1209   ~_media_info() {}
1210 };
1211
1212 class media_info : public _media_info {
1213 public:
1214   static const AVRational clk45k;
1215   char filename[BCTEXTLEN];
1216   int pgm_pid;
1217   int brk, pidx, still;
1218   ArrayList<stream *> streams;
1219   ArrayList<program *> programs;
1220   program *prog()  { return programs[pidx]; }
1221
1222   media_info(const char *fn) {
1223     strcpy(filename, fn);
1224     brk = 0;  pidx = 0;  pgm_pid = -1;  still = 0;
1225   }
1226   ~media_info() {
1227     streams.remove_all_objects();
1228     programs.remove_all_objects();
1229   }
1230
1231   int scan();
1232   int scan(AVFormatContext *fmt_ctx);
1233 };
1234
1235 class Media : public ArrayList<media_info *> {
1236 public:
1237   char *path;
1238   char filename[BCTEXTLEN];
1239   int bd_path(const char *bp, const char *fmt, va_list ap);
1240   int bd_open(const char *fmt, ...);
1241   int bd_backup(const char *fmt, ...);
1242   int bd_copy(const char *ifn, const char *fmt, ...);
1243
1244   index_file idx;
1245   movie_file mov;
1246   ArrayList<clpi_cl *> cl;
1247   ArrayList<mpls_pl *> pl;
1248
1249   void add_movie(uint32_t *ops, int n);
1250   int compose(int ch_interval);
1251   int write(char *fn);
1252
1253   Media() { path = 0;  filename[0] = 0; }
1254   ~Media() {
1255     remove_all_objects();
1256     cl.remove_all_objects();
1257     pl.remove_all_objects();
1258   }
1259 };
1260
1261 #endif
1262
1263 void bs_file::init()
1264 {
1265   fp = 0;
1266   reg = len = 0;
1267   fpos = fsz = 0;
1268 }
1269
1270 int
1271 bs_file::open(const char *fn)
1272 {
1273   fp = fopen(fn,"w");
1274   if( !fp ) perror(fn);
1275   return fp != 0 ? 0 : 1;
1276 }
1277
1278 void
1279 bs_file::close()
1280 {
1281   if( fp ) { fclose(fp); fp = 0; }
1282 }
1283
1284 void
1285 bs_file::write(uint32_t v, int n)
1286 {
1287   uint64_t vv = reg;
1288   vv <<= n;  vv |= v;
1289   reg = vv;  len += n;
1290   while( len >= 8 ) {
1291     len -= 8;
1292     if( fp ) fputc((vv >> len), fp);
1293     if( ++fpos > fsz ) fsz = fpos;
1294   }
1295 }
1296
1297 void
1298 bs_file::writeb(uint8_t * bp, int n)
1299 {
1300   while( --n >= 0 ) write(*bp++, 8);
1301 }
1302
1303 void
1304 bs_file::pad(int n)
1305 {
1306   while( n > 32 ) { write(0, 32);  n -= 32; }
1307   if( n > 0 ) write(0, n);
1308 }
1309
1310 void
1311 bs_file::posb(int64_t n)
1312 {
1313   if( fpos == fsz && n > fpos ) {
1314     padb(n-fpos);
1315     return;
1316   }
1317   fpos = n;
1318   if( fp ) fseek(fp, fpos, SEEK_SET);
1319 }
1320
1321 static bs_file bs;
1322
1323
1324 int
1325 movie_file::write()
1326 {
1327   // output header
1328   bs.writeb("MOBJ", 4);
1329   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1330   int movie_start = 0x0028;
1331   bs.posb(movie_start);
1332   bs_len(bs, 32);
1333   bs.write(0, 32);
1334   bs.write(movies.size(), 16);
1335
1336   for (int i = 0; i < movies.size(); ++i) {
1337     movie_obj *mov = movies[i];
1338     bs.write(mov->resume_intention_flag, 1);
1339     bs.write(mov->menu_call_mask, 1);
1340     bs.write(mov->title_search_mask, 1);
1341     bs.write(0, 13);
1342     ArrayList<command_obj *> &cmds = mov->cmds;
1343     int num_cmds = cmds.size();
1344     bs.write(num_cmds, 16);
1345     for (int j = 0; j < num_cmds; ++j) {
1346       command_obj *cmd = cmds[j];
1347       bs.write(cmd->op_cnt, 3);
1348       bs.write(cmd->grp, 2);
1349       bs.write(cmd->sub_grp, 3);
1350       bs.write(cmd->imm_op1, 1);
1351       bs.write(cmd->imm_op2, 1);
1352       bs.write(0, 2);
1353       bs.write(cmd->branch_opt, 4);
1354       bs.write(0, 4);
1355       bs.write(cmd->cmp_opt, 4);
1356       bs.write(0, 3);
1357       bs.write(cmd->set_opt, 5);
1358       //bs.write(cmd->cmd, 32);
1359       bs.write(cmd->dst, 32);
1360       bs.write(cmd->src, 32);
1361     }
1362   }
1363 //in sony AVCHD
1364 //  bs.write('l', 8);
1365 //  bs.writebcd(year, 16);
1366 //  bs.writebcd(month, 8);
1367 //  bs.writebcd(day, 8);
1368 //  bs.writebcd(hour, 8);
1369 //  bs.writebcd(min, 8);
1370 //  bs.writebcd(sec, 8);
1371   bs_end(bs);
1372   return 0;
1373 }
1374
1375 void
1376 pb_obj::set_hdmv(int id, int pt)
1377 {
1378   obj_typ = obj_hdmv;
1379   pb_typ = pt;
1380   delete [] bdj_name;
1381   bdj_name = 0;
1382   hdmv_id = id;
1383 }
1384
1385 void
1386 pb_obj::set_bdj(char *nm, int pt)
1387 {
1388   obj_typ = obj_bdj;
1389   pb_typ = pt;
1390   delete [] bdj_name;
1391   bdj_name = 0;
1392   bdj_name = cstrdup(nm);
1393 }
1394
1395 void
1396 pb_obj::write_hdmv_obj(int id_ref)
1397 {
1398   bs.write(pb_typ, 2);
1399   bs.write(0, 14);
1400   bs.write(id_ref, 16);
1401   bs.write(0, 32);
1402 }
1403
1404 void
1405 pb_obj::write_bdj_obj(char *name)
1406 {
1407   bs.write(pb_typ, 2);
1408   bs.write(0, 14);
1409   bs.writeb(name, 5);
1410   bs.write(0, 8);
1411 }
1412
1413 void
1414 pb_obj::write_obj()
1415 {
1416   switch (obj_typ) {
1417   case obj_bdj:
1418     write_bdj_obj(bdj_name);
1419     break;
1420   case obj_hdmv:
1421   default:
1422     write_hdmv_obj(hdmv_id);
1423     break;
1424   }
1425 }
1426
1427 void
1428 title_obj::write_obj()
1429 {
1430   bs.write(obj_typ, 2);
1431   bs.write(acc_typ, 2);
1432   bs.write(0, 28);
1433   pb_obj::write_obj();
1434 }
1435
1436
1437 void
1438 index_file::write_pb_obj(pb_obj * pb)
1439 {
1440   bs.write(pb->obj_typ, 2);
1441   bs.write(0, 30);
1442   pb->write_obj();
1443 }
1444
1445 int
1446 index_file::write()
1447 {
1448   // output header
1449   bs.writeb("INDX", 4);
1450   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1451   bs_ofs(bs, 32);
1452   exten.bs_zofs(bs, 32);
1453   int appinfo_start = 0x28;
1454   bs.posb(appinfo_start);
1455   appinf.bs_len(bs, 32);
1456   bs.write(1, 1);
1457   bs.write(initial_output_mode_preference, 1);
1458   bs.write(content_exist_flag, 1);
1459   bs.write(0, 5);
1460   bs.write(video_format, 4);
1461   bs.write(frame_rate, 4);
1462   bs.writeb(user_data, 32);
1463   appinf.bs_end(bs);
1464
1465   // output index
1466   bs_len(bs, 32);
1467   write_pb_obj(&first_play);
1468   write_pb_obj(&top_menu);
1469   bs.write(titles.size(), 16);
1470
1471   for (int i = 0; i < titles.size(); ++i)
1472     titles[i]->write_obj();
1473   bs_end(bs);
1474   exten.bs_len(bs,32);
1475   exten.bs_end(bs);
1476   return 0;
1477 }
1478
1479
1480
1481 int
1482 bdid::write()
1483 {
1484   bs.writeb("BDID",4);
1485   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1486   bs.write(data_start, 32);
1487   bs.write(extension_data_start, 32);
1488   bs.posb(40 - 16);
1489   bs.writeb(org_id, sizeof(org_id));
1490   bs.writeb(disc_id, sizeof(disc_id));
1491   return 0;
1492 }
1493
1494 // XXX - not current referenced
1495 #if 0
1496 int
1497 bdmv_write_extension_data(int start_address,
1498         int (*handler) (int, int, void *), void *handle)
1499 {
1500   int64_t length;
1501   int num_entries, n;
1502
1503   bs.write(length, 32);   /* length of extension data block */
1504   if( length < 1 )
1505     return 1;
1506
1507   bs.pad(32);             /* relative start address of extension data */
1508   bs.pad(24);             /* padding */
1509   bs.write(num_entries, 8);
1510
1511   for (n = 0; n < num_entries; n++) {
1512     bs.write(id1, 16);
1513     bs.write(id2, 16);
1514     bs.write(ext_start, 32);
1515     bs.write(ext_len, 32);
1516     saved_pos = bs.pos() >> 3;
1517     bs.posb(start_address + ext_start);
1518     handler(id1, id2, handle);
1519     bs.posb(saved_pos);
1520   }
1521
1522   return 0;
1523 }
1524 #endif
1525
1526 int
1527 clpi_prog_stream::write()
1528 {
1529   bs.write(pid, 16);
1530   bs_len(bs, 8);
1531
1532   bs.write(coding_type, 8);
1533   switch (coding_type) {
1534   case BLURAY_STREAM_TYPE_VIDEO_MPEG1:
1535   case BLURAY_STREAM_TYPE_VIDEO_MPEG2:
1536   case BLURAY_STREAM_TYPE_VIDEO_VC1:
1537   case BLURAY_STREAM_TYPE_VIDEO_H264:
1538   case BLURAY_STREAM_TYPE_VIDEO_HEVC:
1539   case 0x20:
1540     bs.write(format, 4);
1541     bs.write(rate, 4);
1542     bs.write(aspect, 4);
1543     bs.pad(2);
1544     bs.write(oc_flag, 1);
1545     bs.pad(1);
1546     break;
1547
1548   case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
1549   case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
1550   case BLURAY_STREAM_TYPE_AUDIO_LPCM:
1551   case BLURAY_STREAM_TYPE_AUDIO_AC3:
1552   case BLURAY_STREAM_TYPE_AUDIO_DTS:
1553   case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
1554   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
1555   case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
1556   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
1557   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS_SECONDARY:
1558   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_SECONDARY:
1559     bs.write(format, 4);
1560     bs.write(rate, 4);
1561     bs.writeb(lang, 3);
1562     break;
1563
1564   case BLURAY_STREAM_TYPE_SUB_PG:
1565   case BLURAY_STREAM_TYPE_SUB_IG:
1566   case 0xa0:
1567     bs.writeb(lang, 3);
1568     break;
1569
1570   case BLURAY_STREAM_TYPE_SUB_TEXT:
1571     bs.write(char_code, 8);
1572     bs.writeb(lang, 3);
1573     break;
1574
1575   default:
1576     fprintf(stderr, "clpi_prog_stream: unrecognized coding type %02x\n",
1577             coding_type);
1578     return 1;
1579   };
1580
1581   bs.padb(0x15 - bs_posb(bs));
1582   bs_end(bs);
1583   return 0;
1584 }
1585
1586 int
1587 clpi_cl::write_header()
1588 {
1589   bs.writeb("HDMV", 4);
1590   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1591   bs.write(sequence_info_start_addr, 32);
1592   bs.write(program_info_start_addr, 32);
1593   bs.write(cpi_start_addr, 32);
1594   bs.write(clip_mark_start_addr, 32);
1595   bs.write(ext_data_start_addr, 32);
1596   return 0;
1597 }
1598
1599 int
1600 clpi_atc_delta::write()
1601 {
1602   bs.write(delta, 32);
1603   bs.writeb(file_id, 5);
1604   bs.writeb(file_code, 4);
1605   bs.pad(8);
1606   return 0;
1607 }
1608
1609 int
1610 clpi_clip_info::write()
1611 {
1612   bs.posb(40);
1613   bs_len(bs, 32);
1614
1615   bs.pad(16);                   // reserved
1616   bs.write(clip_stream_type, 8);
1617   bs.write(application_type, 8);
1618   bs.pad(31);                   // skip reserved 31 bits
1619   bs.write(is_atc_delta, 1);
1620   bs.write(ts_recording_rate, 32);
1621   bs.write(num_source_packets, 32);
1622
1623   bs.padb(128);                 // Skip reserved 128 bytes
1624
1625   // ts type info block
1626   int ts_len = 30;
1627   bs.write(ts_len, 16);
1628   int64_t pos = bs.posb();
1629   if( ts_len ) {
1630     bs.write(ts_type_info.validity, 8);
1631     bs.writeb(ts_type_info.format_id, 4);
1632     // pad the stuff we don't know anything about
1633     bs.padb(ts_len - (bs.posb() - pos));
1634   }
1635
1636   if( is_atc_delta ) {
1637     bs.pad(8);                  // Skip reserved byte
1638     bs.write(atc_delta.size(), 8);
1639     for( int ii=0; ii < atc_delta.size(); ++ii )
1640       if( atc_delta[ii]->write() ) return 1;
1641   }
1642
1643   // font info
1644   if( application_type == 6 /* Sub TS for a sub-path of Text subtitle */  ) {
1645     bs.pad(8);
1646     bs.write(font_info.font.size(), 8);
1647     if( font_info.font.size() ) {
1648       for( int ii=0; ii < font_info.font.size(); ++ii ) {
1649         bs.writeb(font_info.font[ii]->file_id, 5);
1650         bs.pad(8);
1651       }
1652     }
1653   }
1654
1655   bs_end(bs);
1656   return 0;
1657 }
1658
1659 int
1660 clpi_stc_seq::write()
1661 {
1662   bs.write(pcr_pid, 16);
1663   bs.write(spn_stc_start, 32);
1664   bs.write(presentation_start_time, 32);
1665   bs.write(presentation_end_time, 32);
1666   return 0;
1667 }
1668
1669 int
1670 clpi_atc_seq::write()
1671 {
1672   bs.write(spn_atc_start, 32);
1673   bs.write(stc_seq.size(), 8);
1674   bs.write(offset_stc_id, 8);
1675
1676   for( int ii=0; ii < stc_seq.size(); ++ii )
1677     if( stc_seq[ii]->write() ) return 1;
1678   return 0;
1679 }
1680
1681 int
1682 clpi_sequences::write()
1683 {
1684   bs_len(bs, 32);
1685   bs.padb(1);                   // reserved byte
1686   bs.write(size(), 8);
1687   for( int ii=0; ii < size(); ++ii )
1688     if( get(ii)->write() ) return 1;
1689   bs_end(bs);
1690   return 0;
1691 }
1692
1693 int
1694 clpi_prog::write()
1695 {
1696   bs.write(spn_program_sequence_start, 32);
1697   bs.write(program_map_pid, 16);
1698   bs.write(streams.size(), 8);
1699   bs.write(num_groups, 8);
1700   for( int ii=0; ii < streams.size(); ++ii )
1701     if( streams[ii]->write() ) return 1;
1702   return 0;
1703 }
1704
1705 int
1706 clpi_programs::write()
1707 {
1708   bs_len(bs, 32);
1709   bs.padb(1);                   // reserved byte
1710   bs.write(size(), 8);
1711   for( int ii=0; ii < size(); ++ii )
1712     if( get(ii)->write() ) return 1;
1713   bs_end(bs);
1714   return 0;
1715 }
1716
1717 int
1718 clpi_ep_coarse::write()
1719 {
1720   bs.write(ref_ep_fine_id, 18);
1721   bs.write(pts_ep, 14);
1722   bs.write(spn_ep, 32);
1723   return 0;
1724 }
1725
1726 int
1727 clpi_ep_fine::write()
1728 {
1729   bs.write(is_angle_change_point, 1);
1730   bs.write(i_end_position_offset, 3);
1731   bs.write(pts_ep, 11);
1732   bs.write(spn_ep, 17);
1733   return 0;
1734 }
1735
1736 int
1737 clpi_ep_map_entry::write(uint32_t ep_map_pos)
1738 {
1739   bs.write(pid, 16);
1740   bs.pad(10);
1741   bs.write(ep_stream_type, 4);
1742   bs.write(coarse.size(), 16);
1743   bs.write(fine.size(), 18);
1744   bs.write(ep_map_stream_start_addr - ep_map_pos, 32);
1745   return 0;
1746 }
1747
1748 int
1749 clpi_ep_map_entry::write_map()
1750 {
1751   ep_map_stream_start_addr = bs.posb();
1752   bs.write(fine_start, 32);
1753
1754   for( int ii=0; ii < coarse.size(); ++ii )
1755     if( coarse[ii]->write() ) return 1;
1756
1757   fine_start = bs.posb() - ep_map_stream_start_addr;
1758   for( int ii=0; ii < fine.size(); ++ii )
1759     if( fine[ii]->write() ) return 1;
1760
1761   return 0;
1762 }
1763
1764 int
1765 clpi_cpi::write()
1766 {
1767   bs_len(bs, 32);
1768   bs.pad(12);
1769   bs.write(type, 4);
1770   uint32_t ep_map_pos = bs.posb();
1771
1772   // EP Map starts here
1773   bs.pad(8);
1774   bs.write(size(), 8);
1775
1776   for( int ii=0; ii < size(); ++ii )
1777     if( get(ii)->write(ep_map_pos) ) return 1;
1778
1779   for( int ii=0; ii < size(); ++ii )
1780     if( get(ii)->write_map() ) return 1;
1781
1782   bs_end(bs);
1783   return 0;
1784 }
1785
1786 int
1787 clpi_cmrk::write()
1788 {
1789   bs_len(bs, 32);
1790   bs_end(bs);
1791   return 0;
1792 }
1793
1794 int
1795 clpi_extents::write()
1796 {
1797   bs_len(bs, 32);
1798   bs.write(size(), 32);
1799   for( int ii=0; ii < size(); ++ii )
1800     bs.write(get(ii), 32);
1801   return 0;
1802 }
1803
1804 int
1805 clpi_cl::write_clpi_extension(int id1, int id2, void *handle)
1806 {
1807   clpi_cl *cl = (clpi_cl *) handle;
1808
1809   if( id1 == 1 ) {
1810     if( id2 == 2 ) {
1811       // LPCM down mix coefficient
1812       //write_lpcm_down_mix_coeff(&cl->lpcm_down_mix_coeff);
1813       return 0;
1814     }
1815   }
1816
1817   if( id1 == 2 ) {
1818     if( id2 == 4 ) {
1819       // Extent start point
1820       return cl->extents.write();
1821     }
1822     if( id2 == 5 ) {
1823       // ProgramInfo SS
1824       return cl->programs_ss.write();
1825     }
1826     if( id2 == 6 ) {
1827       // CPI SS
1828       return cl->cpi_ss.write();
1829     }
1830   }
1831
1832   fprintf(stderr, "write_clpi_extension(): unhandled extension %d.%d\n", id1, id2);
1833   return 1;
1834 }
1835
1836 int
1837 clpi_cl::write()
1838 {
1839   if( write_header() ) return 1;
1840   if( clip.write() ) return 1;
1841   sequence_info_start_addr = bs.posb();
1842   if( sequences.write() ) return 1;
1843   program_info_start_addr = bs.posb();
1844   if( programs.write() ) return 1;
1845   cpi_start_addr = bs.posb();
1846   if( cpi.write() ) return 1;
1847   clip_mark_start_addr = bs.posb();
1848   if( cmrk.write() ) return 1;
1849 //if( has_ext_data ) {
1850 //  ext_data_start_addr = bs.pos();
1851 //  bdmv_write_extension_data(write_clpi_extension, this);
1852 //}
1853   return 0;
1854 }
1855
1856 int
1857 bd_uo_mask::write()
1858 {
1859   bs.write(menu_call, 1);
1860   bs.write(title_search, 1);
1861   bs.write(chapter_search, 1);
1862   bs.write(time_search, 1);
1863   bs.write(skip_to_next_point, 1);
1864   bs.write(skip_to_prev_point, 1);
1865   bs.write(play_firstplay, 1);
1866   bs.write(stop, 1);
1867   bs.write(pause_on, 1);
1868   bs.write(pause_off, 1);
1869   bs.write(still_off, 1);
1870   bs.write(forward, 1);
1871   bs.write(backward, 1);
1872   bs.write(resume, 1);
1873   bs.write(move_up, 1);
1874   bs.write(move_down, 1);
1875   bs.write(move_left, 1);
1876   bs.write(move_right, 1);
1877   bs.write(select, 1);
1878   bs.write(activate, 1);
1879   bs.write(select_and_activate, 1);
1880   bs.write(primary_audio_change, 1);
1881   bs.pad(1);
1882   bs.write(angle_change, 1);
1883   bs.write(popup_on, 1);
1884   bs.write(popup_off, 1);
1885   bs.write(pg_enable_disable, 1);
1886   bs.write(pg_change, 1);
1887   bs.write(secondary_video_enable_disable, 1);
1888   bs.write(secondary_video_change, 1);
1889   bs.write(secondary_audio_enable_disable, 1);
1890   bs.write(secondary_audio_change, 1);
1891   bs.pad(1);
1892   bs.write(pip_pg_change, 1);
1893   bs.pad(30);
1894   return 0;
1895 }
1896
1897 int
1898 mpls_ai::write()
1899 {
1900   bs_len(bs, 32);
1901   bs.pad(8);              // Reserved
1902   bs.write(playback_type, 8);
1903   if (playback_type == BLURAY_PLAYBACK_TYPE_RANDOM ||
1904       playback_type == BLURAY_PLAYBACK_TYPE_SHUFFLE ) {
1905     bs.write(playback_count, 16);
1906   }
1907   else {
1908     bs.pad(16);           // Reserved
1909   }
1910   uo_mask.write();
1911   bs.write(random_access_flag, 1);
1912   bs.write(audio_mix_flag, 1);
1913   bs.write(lossless_bypass_flag, 1);
1914   bs.pad(13);             // Reserved
1915   bs_end(bs);
1916   return 0;
1917 }
1918
1919 int
1920 mpls_pl::write_header()
1921 {
1922   bs.writeb("MPLS", 4);
1923   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1924   bs.write(list_pos, 32);
1925   bs.write(mark_pos, 32);
1926   bs.write(ext_pos, 32);
1927   bs.pad(160);            // Skip 160 reserved bits
1928   app_info.write();
1929   return 0;
1930 }
1931
1932 int mpls_stream::
1933 write()
1934 {
1935   strm.bs_len(bs, 8);
1936
1937   bs.write(stream_type, 8);
1938   switch (stream_type) {
1939   case 1:
1940     bs.write(pid, 16);
1941     break;
1942
1943   case 2:
1944   case 4:
1945     bs.write(subpath_id, 8);
1946     bs.write(subclip_id, 8);
1947     bs.write(pid, 16);
1948     break;
1949
1950   case 3:
1951     bs.write(subpath_id, 8);
1952     bs.write(pid, 16);
1953     break;
1954
1955   default:
1956     fprintf(stderr, "unrecognized mpls stream type %02x\n", stream_type);
1957     break;
1958   };
1959   bs.padb(9 - strm.bs_posb(bs));
1960   strm.bs_end(bs);
1961
1962   code.bs_len(bs, 8);
1963   bs.write(coding_type, 8);
1964   switch (coding_type) {
1965   case BLURAY_STREAM_TYPE_VIDEO_MPEG1:
1966   case BLURAY_STREAM_TYPE_VIDEO_MPEG2:
1967   case BLURAY_STREAM_TYPE_VIDEO_VC1:
1968   case BLURAY_STREAM_TYPE_VIDEO_H264:
1969   case BLURAY_STREAM_TYPE_VIDEO_HEVC:
1970     bs.write(format, 4);
1971     bs.write(rate, 4);
1972     break;
1973
1974   case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
1975   case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
1976   case BLURAY_STREAM_TYPE_AUDIO_LPCM:
1977   case BLURAY_STREAM_TYPE_AUDIO_AC3:
1978   case BLURAY_STREAM_TYPE_AUDIO_DTS:
1979   case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
1980   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
1981   case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
1982   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
1983   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS_SECONDARY:
1984   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_SECONDARY:
1985     bs.write(format, 4);
1986     bs.write(rate, 4);
1987     bs.writeb(lang, 3);
1988     break;
1989
1990   case BLURAY_STREAM_TYPE_SUB_PG:
1991   case BLURAY_STREAM_TYPE_SUB_IG:
1992     bs.writeb(lang, 3);
1993     break;
1994
1995   case BLURAY_STREAM_TYPE_SUB_TEXT:
1996     bs.write(char_code, 8);
1997     bs.writeb(lang, 3);
1998     break;
1999
2000   default:
2001     fprintf(stderr, "mpls_stream: unrecognized coding type %02x\n", coding_type);
2002     break;
2003   };
2004   bs.padb(5 - code.bs_posb(bs));
2005   code.bs_end(bs);
2006   return 0;
2007 }
2008
2009 int
2010 mpls_stn::write()
2011 {
2012   bs_len(bs, 16);
2013   bs.pad(16);             // Skip 2 reserved bytes
2014
2015   bs.write(video.size(), 8);
2016   bs.write(audio.size(), 8);
2017   bs.write(pg.size() - num_pip_pg, 8);
2018   bs.write(ig.size(), 8);
2019   bs.write(secondary_audio.size(), 8);
2020   bs.write(secondary_video.size(), 8);
2021   bs.write(num_pip_pg, 8);
2022
2023   // 5 reserve bytes
2024   bs.pad(5 * 8);
2025
2026   // Primary Video Streams
2027   for( int ii=0; ii < video.size(); ++ii )
2028     if( video[ii]->write() ) return 1;
2029
2030   // Primary Audio Streams
2031   for( int ii=0; ii < audio.size(); ++ii )
2032     if( audio[ii]->write() ) return 1;
2033
2034   // Presentation Graphic Streams
2035   for( int ii=0; ii < pg.size(); ++ii )
2036     if( pg[ii]->write() ) return 1;
2037
2038   // Interactive Graphic Streams
2039   for( int ii=0; ii < ig.size(); ++ii )
2040     if( ig[ii]->write() ) return 1;
2041
2042   // Secondary Audio Streams
2043   for( int ii=0; ii < secondary_audio.size(); ++ii ) {
2044     if( secondary_audio[ii]->write() ) return 1;
2045     // Read Secondary Audio Extra Attributes
2046     bs.write(sa_primary_audio_ref.size(), 8);
2047     bs.pad(8);
2048     for( int jj=0; jj < sa_primary_audio_ref.size(); ++jj )
2049       bs.write(sa_primary_audio_ref[jj], 8);
2050     if( sa_primary_audio_ref.size() % 2) bs.pad(8 );
2051   }
2052
2053   // Secondary Video Streams
2054   for( int ii=0; ii < secondary_video.size(); ++ii ) {
2055     if( secondary_video[ii]->write() ) return 1;
2056     // Read Secondary Video Extra Attributes
2057     bs.write(sv_secondary_audio_ref.size(), 8);
2058     bs.pad(8);
2059     for( int jj=0; jj < sv_secondary_audio_ref.size(); ++jj )
2060       bs.write(sv_secondary_audio_ref[jj], 8);
2061     if( sv_secondary_audio_ref.size() % 2) bs.pad(8 );
2062     bs.write(sv_pip_pg_ref.size(), 8);
2063     bs.pad(8);
2064     for( int jj=0; jj < sv_pip_pg_ref.size(); ++jj )
2065       bs.write(sv_pip_pg_ref[jj], 8);
2066     if( sv_pip_pg_ref.size() % 2) bs.pad(8 );
2067   }
2068
2069   bs_end(bs);
2070   return 0;
2071 }
2072
2073 int
2074 mpls_pi::write()
2075 {
2076   bs_len(bs, 16);
2077   // Primary Clip identifer
2078   bs.writeb(clip[0]->clip_id, 5);
2079   bs.writeb(clip[0]->codec_id, 4); // "M2TS"
2080   bs.pad(11); // Skip reserved 11 bits
2081
2082   bs.write(is_multi_angle, 1);
2083   bs.write(connection_condition, 4);  // 0x01, 0x05, 0x06
2084
2085   bs.write(clip[0]->stc_id, 8);
2086   bs.write(in_time, 32);
2087   bs.write(out_time, 32);
2088
2089   uo_mask.write();
2090   bs.write(random_access_flag, 1);
2091   bs.pad(7);
2092   bs.write(still_mode, 8);
2093   if( still_mode == 0x01 ) {
2094     bs.write(still_time, 16);
2095   }
2096   else {
2097     bs.pad(16);
2098   }
2099
2100   if( is_multi_angle ) {
2101     bs.write(clip.size(), 8);
2102     bs.pad(6);
2103     bs.write(is_different_audio, 1);
2104     bs.write(is_seamless_angle, 1);
2105   }
2106
2107   for( int ii=1; ii < clip.size(); ++ii ) {
2108     bs.writeb(clip[ii]->clip_id, 5);
2109     bs.writeb(clip[ii]->codec_id, 4); // "M2TS"
2110     bs.write(clip[ii]->stc_id, 8);
2111   }
2112
2113   if( stn.write() ) return 1;
2114
2115   bs_end(bs);
2116   return 0;
2117 }
2118
2119 int
2120 mpls_sub_pi::write()
2121 {
2122   bs_len(bs, 16);
2123   // Primary Clip identifer
2124   bs.writeb(clip[0]->clip_id, 5);
2125   bs.writeb(clip[0]->codec_id, 4); // "M2TS"
2126   bs.pad(27);
2127
2128   bs.write(connection_condition, 4); // 0x01, 0x05, 0x06
2129
2130   bs.write(is_multi_clip, 1);
2131   bs.write(clip[0]->stc_id, 8);
2132   bs.write(in_time, 32);
2133   bs.write(out_time, 32);
2134   bs.write(sync_play_item_id, 16);
2135   bs.write(sync_pts, 32);
2136
2137   if( is_multi_clip )
2138     bs.write(clip.size(), 8);
2139
2140   for( int ii=1; ii < clip.size(); ++ii ) {
2141     // Primary Clip identifer
2142     bs.writeb(clip[ii]->clip_id, 5);
2143     bs.writeb(clip[ii]->codec_id, 4); // "M2TS"
2144     bs.write(clip[ii]->stc_id, 8);
2145   }
2146
2147   bs_end(bs);
2148   return 0;
2149 }
2150
2151 int
2152 mpls_sub::write()
2153 {
2154   bs_len(bs, 32);
2155   bs.pad(8);
2156   bs.write(type, 8);
2157   bs.pad(15);
2158   bs.write(is_repeat, 1);
2159   bs.pad(8);
2160   bs.write(sub_play_item.size(), 8);
2161
2162   for( int ii=0; ii < sub_play_item.size(); ++ii )
2163     if( sub_play_item[ii]->write() ) return 1;
2164
2165   bs_end(bs);
2166   return 0;
2167 }
2168
2169 int
2170 mpls_plm::write()
2171 {
2172   bs.write(mark_id, 8);
2173   bs.write(mark_type, 8);
2174   bs.write(play_item_ref, 16);
2175   bs.write(time, 32);
2176   bs.write(entry_es_pid, 16);
2177   bs.write(duration, 32);
2178   return 0;
2179 }
2180
2181 int
2182 mpls_pl::write_playlistmark()
2183 {
2184   mark.bs_len(bs, 32);
2185   // Then get the number of marks
2186   bs.write(play_mark.size(), 16);
2187
2188   for( int ii=0; ii < play_mark.size(); ++ii )
2189     if( play_mark[ii]->write() ) return 1;
2190
2191   mark.bs_end(bs);
2192   return 0;
2193 }
2194
2195 int
2196 mpls_pl::write_playlist()
2197 {
2198   play.bs_len(bs,32);
2199
2200   // Skip reserved bytes
2201   bs.pad(16);
2202
2203   bs.write(play_item.size(), 16);
2204   bs.write(sub_path.size(), 16);
2205
2206   for( int ii=0; ii < play_item.size(); ++ii )
2207     if( play_item[ii]->write() ) return 1;
2208
2209   for( int ii=0; ii < sub_path.size(); ++ii )
2210     if( sub_path[ii]->write() ) return 1;
2211
2212   play.bs_end(bs);
2213   return 0;
2214 }
2215
2216 int
2217 mpls_pip_data::write()
2218 {
2219   bs.write(time, 32);
2220   bs.write(xpos, 12);
2221   bs.write(ypos, 12);
2222   bs.write(scale_factor, 4);
2223   bs.pad(4);
2224   return 0;
2225 }
2226
2227 int
2228 mpls_pip_metadata::write(uint32_t start_address)
2229 {
2230
2231   bs.write(clip_ref, 16);
2232   bs.write(secondary_video_ref, 8);
2233   bs.pad(8);
2234   bs.write(timeline_type, 4);
2235   bs.write(luma_key_flag, 1);
2236   bs.write(trick_play_flag, 1);
2237   bs.pad(10);
2238   if( luma_key_flag ) {
2239     bs.pad(8);
2240     bs.write(upper_limit_luma_key, 8);
2241   }
2242   else {
2243     bs.pad(16);
2244   }
2245   bs.pad(16);
2246
2247   uint32_t data_address = 0;  // XXX
2248   bs.write(data_address, 32);
2249
2250   int64_t pos = bs.pos() / 8;
2251   bs.posb(start_address + data_address);
2252
2253   bs.write(data.size(), 16);
2254   if( data.size() < 1 ) return 1;
2255
2256   for( int ii=0; ii < data.size(); ++ii )
2257     if( data[ii]->write() ) return 1;
2258
2259   bs.posb(pos);
2260   return 0;
2261 }
2262
2263 int
2264 mpls_pl::write_pip_metadata_extension()
2265 {
2266   uint32_t pos = bs.posb();
2267   pipm.bs_len(bs, 32);
2268
2269   bs.write(ext_pip_data.size(), 16);
2270   for( int ii=0; ii < ext_pip_data.size(); ++ii )
2271     if( ext_pip_data[ii]->write(pos) ) return 1;
2272
2273   pipm.bs_end(bs);
2274   return 0;
2275 }
2276
2277 int
2278 mpls_pl::write_subpath_extension()
2279 {
2280   subx.bs_len(bs, 32);
2281
2282   bs.write(ext_sub_path.size(), 16);
2283   for( int ii=0; ii < ext_sub_path.size(); ++ii )
2284     if( ext_sub_path[ii]->write() ) return 1;
2285
2286   subx.bs_end(bs);
2287   return 0;
2288 }
2289
2290 int
2291 clpi_cl::write_mpls_extension(int id1, int id2, void *handle)
2292 {
2293   mpls_pl *pl = (mpls_pl *) handle;
2294
2295   if( id1 == 1 ) {
2296     if( id2 == 1 ) {
2297       // PiP metadata extension
2298       return pl->write_pip_metadata_extension();
2299     }
2300   }
2301
2302   if( id1 == 2 ) {
2303     if( id2 == 1 ) {
2304       return 0;
2305     }
2306     if( id2 == 2 ) {
2307       // SubPath entries extension
2308       return pl->write_subpath_extension();
2309     }
2310   }
2311
2312   return 0;
2313 }
2314
2315 int mpls_pl::
2316 write()
2317 {
2318   int ret = write_header();
2319   list_pos = bs.posb();;
2320   if( !ret ) ret = write_playlist();
2321   mark_pos = bs.posb();
2322   if( !ret ) ret = write_playlistmark();
2323 //if( has_pls_extension ) {
2324 //  ext_pos = bs.posb();
2325 //  bdmv_write_extension_data(write_mpls_extension, pl);
2326   return ret;
2327 }
2328
2329 static int
2330 mk_dir(char *path)
2331 {
2332   if( !mkdir(path, 0777) )
2333     return 0;
2334   perror(path);
2335   return 1;
2336 }
2337
2338 static int
2339 mk_bdmv_dir(char *bdmv_path)
2340 {
2341   if( mk_dir(bdmv_path) )
2342     return 1;
2343   char bdjo_path[BCTEXTLEN];
2344   sprintf(bdjo_path, "%s/BDJO", bdmv_path);
2345   if( mk_dir(bdjo_path) )
2346     return 1;
2347   char clipinf_path[BCTEXTLEN];
2348   sprintf(clipinf_path, "%s/CLIPINF", bdmv_path);
2349   if( mk_dir(clipinf_path) )
2350     return 1;
2351   char jar_path[BCTEXTLEN];
2352   sprintf(jar_path, "%s/JAR", bdmv_path);
2353   if( mk_dir(jar_path) )
2354     return 1;
2355   char playlist_path[BCTEXTLEN];
2356   sprintf(playlist_path, "%s/PLAYLIST", bdmv_path);
2357   if( mk_dir(playlist_path) )
2358     return 1;
2359   return 0;
2360 }
2361
2362 static int
2363 mkbdmv(char *path)
2364 {
2365   char bdmv_path[BCTEXTLEN];
2366   sprintf(bdmv_path, "%s/BDMV", path);
2367   if( mk_bdmv_dir(bdmv_path) ) return 1;
2368   char cert_path[BCTEXTLEN];
2369   sprintf(cert_path, "%s/CERTIFICATE", path);
2370   if( mk_bdmv_dir(cert_path) ) return 1;
2371   char cert_backup[BCTEXTLEN];
2372   sprintf(cert_backup, "%s/BACKUP", cert_path);
2373   if( mk_bdmv_dir(cert_backup) ) return 1;
2374   char stream_path[BCTEXTLEN];
2375   sprintf(stream_path, "%s/STREAM", bdmv_path);
2376   if( mk_dir(stream_path) ) return 1;
2377   char auxdata_path[BCTEXTLEN];
2378   sprintf(auxdata_path, "%s/AUXDATA", bdmv_path);
2379   if( mk_dir(auxdata_path) ) return 1;
2380   char meta_path[BCTEXTLEN];
2381   sprintf(meta_path, "%s/META", bdmv_path);
2382   if( mk_dir(meta_path) ) return 1;
2383   char backup_path[BCTEXTLEN];
2384   sprintf(backup_path, "%s/BACKUP", bdmv_path);
2385   if( mk_bdmv_dir(backup_path) ) return 1;
2386   return 0;
2387 }
2388
2389 int program::
2390 build_toc(clpi_ep_map_entry *map)
2391 {
2392   clpi_ep_coarse *cp = 0;
2393   marks.sort(mark::cmpr);
2394   uint16_t ep_pid = map->pid;
2395   int64_t last_pts = -1, last_pkt = -1;
2396   for( int ii=0; ii<marks.size(); ++ii ) {
2397     mark *mp = marks[ii];
2398     if( mp->pid != ep_pid ) continue;
2399     int64_t pts = mp->pts;
2400     if( last_pts >= pts ) continue;
2401     last_pts = pts;
2402     uint32_t pkt = mp->pos / BLURAY_TS_PKTSZ;
2403     if( last_pkt >= pkt ) continue;
2404     last_pkt = pkt;
2405     int64_t coarse_pts = (pts >> 18); // & ~0x01;
2406     int64_t fine_pts = (pts & 0x7ffff) >> 8;
2407     uint32_t mpkt = pkt & ~0x1ffff;
2408     if( !cp || cp->pts_ep != coarse_pts || mpkt > cp->spn_ep ) {
2409       cp = new clpi_ep_coarse();
2410       map->coarse.append(cp);
2411       cp->ref_ep_fine_id = map->fine.size();
2412       cp->pts_ep = coarse_pts;
2413       cp->spn_ep = pkt;
2414     }
2415     clpi_ep_fine *fp = new clpi_ep_fine();
2416     map->fine.append(fp);
2417     fp->is_angle_change_point = 0;
2418 // XXX - dont know what this is
2419     fp->i_end_position_offset = 1;
2420     fp->pts_ep = fine_pts;
2421     fp->spn_ep = pkt & 0x1ffff;
2422   }
2423   return 0;
2424 }
2425
2426 const AVRational media_info::clk45k = { 1, 45000 };
2427
2428 static int bd_coding_type(AVCodecID codec_id)
2429 {
2430   int coding_type = 0;
2431   switch (codec_id) {
2432   case AV_CODEC_ID_MPEG1VIDEO:
2433     coding_type = BLURAY_STREAM_TYPE_VIDEO_MPEG1;
2434     break;
2435   case AV_CODEC_ID_MPEG2VIDEO:
2436     coding_type = BLURAY_STREAM_TYPE_VIDEO_MPEG2;
2437     break;
2438   case AV_CODEC_ID_H264:
2439     coding_type = BLURAY_STREAM_TYPE_VIDEO_H264;
2440     break;
2441   case AV_CODEC_ID_HEVC:
2442     coding_type = BLURAY_STREAM_TYPE_VIDEO_HEVC;
2443     break;
2444   case AV_CODEC_ID_MP2:
2445     coding_type = BLURAY_STREAM_TYPE_AUDIO_MPEG1;
2446     break;
2447   case AV_CODEC_ID_MP3:
2448     coding_type = BLURAY_STREAM_TYPE_AUDIO_MPEG2;
2449     break;
2450   case AV_CODEC_ID_AC3:
2451     coding_type = BLURAY_STREAM_TYPE_AUDIO_AC3;
2452     break;
2453   case AV_CODEC_ID_EAC3:
2454     coding_type = BLURAY_STREAM_TYPE_AUDIO_AC3PLUS;
2455     break;
2456   case AV_CODEC_ID_DTS:
2457     coding_type = BLURAY_STREAM_TYPE_AUDIO_DTS;
2458     break;
2459   case AV_CODEC_ID_TRUEHD:
2460     coding_type = BLURAY_STREAM_TYPE_AUDIO_TRUHD;
2461     break;
2462   case AV_CODEC_ID_PCM_BLURAY:
2463     coding_type = BLURAY_STREAM_TYPE_AUDIO_LPCM;
2464     break;
2465   case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
2466     coding_type = BLURAY_STREAM_TYPE_SUB_PG;
2467     break;
2468   default:
2469     fprintf(stderr, "unknown bluray codec type %s\n", avcodec_get_name(codec_id));
2470     exit(1);
2471   }
2472   return coding_type;
2473 }
2474
2475 static int bd_audio_format(int channels)
2476 {
2477   int audio_format = 0;
2478   switch( channels ) {
2479   case 1:
2480     audio_format = BLURAY_AUDIO_FORMAT_MONO;
2481     break;
2482   case 2:
2483     audio_format = BLURAY_AUDIO_FORMAT_STEREO;
2484     break;
2485   case 6:
2486     audio_format = BLURAY_AUDIO_FORMAT_MULTI_CHAN;
2487     break;
2488   default:
2489     fprintf(stderr, "unknown bluray audio format %d ch\n", channels);
2490     exit(1);
2491   }
2492   return audio_format;
2493 }
2494
2495 static int bd_audio_rate(int rate)
2496 {
2497   int audio_rate = 0;
2498   switch( rate ) {
2499   case 48000:  audio_rate = BLURAY_AUDIO_RATE_48;  break;
2500   case 96000:  audio_rate = BLURAY_AUDIO_RATE_96;  break;
2501   case 192000: audio_rate = BLURAY_AUDIO_RATE_192; break;
2502   default:
2503     fprintf(stderr, "unknown bluray audio rate %d\n", rate);
2504     exit(1);
2505   }
2506   return audio_rate;
2507 }
2508
2509 static int bd_video_format(int w, int h, int ilace)
2510 {
2511   if( w ==  720 && h ==  480    &&  ilace   ) return BLURAY_VIDEO_FORMAT_480I;
2512   if( w ==  720 && h ==  576    &&  ilace   ) return BLURAY_VIDEO_FORMAT_576I;
2513   if( w ==  720 && h ==  480    && !ilace   ) return BLURAY_VIDEO_FORMAT_480P;
2514   if( w ==  720 && h ==  576    && !ilace   ) return BLURAY_VIDEO_FORMAT_576P;
2515 // this seems to be overly restrictive
2516   if( w == 1280 && h ==  720 /* && !ilace*/ ) return BLURAY_VIDEO_FORMAT_720P;
2517   if( w == 1440 && h == 1080 /* &&  ilace*/ ) return BLURAY_VIDEO_FORMAT_1080I;
2518   if( w == 1920 && h == 1080 /* && !ilace*/ ) return BLURAY_VIDEO_FORMAT_1080P;
2519   if( w == 3840 && h == 2160 &&  !ilace ) return BLURAY_VIDEO_FORMAT_2160P;
2520
2521   fprintf(stderr, "unknown bluray video format %dx%d %silace\n",
2522     w, h, !ilace ? "not " : "");
2523   exit(1);
2524 }
2525
2526 static int bd_video_rate(double rate)
2527 {
2528   if( fabs(rate-23.976) < 0.01 ) return BLURAY_VIDEO_RATE_24000_1001;
2529   if( fabs(rate-24.000) < 0.01 ) return BLURAY_VIDEO_RATE_24;
2530   if( fabs(rate-25.000) < 0.01 ) return BLURAY_VIDEO_RATE_25;
2531   if( fabs(rate-29.970) < 0.01 ) return BLURAY_VIDEO_RATE_30000_1001;
2532   if( fabs(rate-50.000) < 0.01 ) return BLURAY_VIDEO_RATE_50;
2533   if( fabs(rate-59.940) < 0.01 ) return BLURAY_VIDEO_RATE_60000_1001;
2534   fprintf(stderr, "unknown bluray video framerate %5.2f\n",rate);
2535   exit(1);
2536 }
2537
2538 static int bd_aspect_ratio(int w, int h, double ratio)
2539 {
2540   double aspect = (w * ratio) / h;
2541   if( fabs(aspect-1.333) < 0.01 ) return BLURAY_ASPECT_RATIO_4_3;
2542   if( fabs(aspect-1.777) < 0.01 ) return BLURAY_ASPECT_RATIO_16_9;
2543   return w == 720 ? BLURAY_ASPECT_RATIO_4_3 : BLURAY_ASPECT_RATIO_16_9;
2544   fprintf(stderr, "unknown bluray aspect ratio %5.3f\n",aspect);
2545   exit(1);
2546 }
2547
2548 static int field_probe(AVFormatContext *fmt_ctx, AVStream *st)
2549 {
2550   AVDictionary *copts = 0;
2551   //av_dict_copy(&copts, opts, 0);
2552   AVCodecID codec_id = st->codecpar->codec_id;
2553 #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(58,134,100)
2554   AVCodec *decoder = avcodec_find_decoder(codec_id);
2555 #endif
2556 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59,16,100)
2557   const AVCodec *decoder = avcodec_find_decoder(codec_id);
2558 #endif
2559   AVCodecContext *ctx = avcodec_alloc_context3(decoder);
2560   if( !ctx ) {
2561     fprintf(stderr,"codec alloc failed\n");
2562     return -1;
2563   }
2564   avcodec_parameters_to_context(ctx, st->codecpar);
2565   if( avcodec_open2(ctx, decoder, &copts) < 0 ) {
2566     fprintf(stderr,"codec open failed\n");
2567     return -1;
2568   }
2569   av_dict_free(&copts);
2570
2571   AVFrame *ipic = av_frame_alloc();
2572   AVPacket ipkt;
2573   av_init_packet(&ipkt);
2574   int ilaced = -1;
2575   for( int retrys=100; --retrys>=0 && ilaced<0; ) {
2576     av_packet_unref(&ipkt);
2577     int ret = av_read_frame(fmt_ctx, &ipkt);
2578     if( ret == AVERROR_EOF ) break;
2579     if( ret != 0 ) continue;
2580     if( ipkt.stream_index != st->index ) continue;
2581     if( !ipkt.data || !ipkt.size ) continue;
2582     ret = avcodec_send_packet(ctx, &ipkt);
2583     if( ret < 0 ) {
2584       fprintf(stderr, "avcodec_send_packet failed\n");
2585       break;
2586     }
2587     ret = avcodec_receive_frame(ctx, ipic);
2588     if( ret >= 0 ) {
2589       ilaced = ipic->interlaced_frame ? 1 : 0;
2590       break;
2591     }
2592     if( ret != AVERROR(EAGAIN) )
2593       fprintf(stderr, "avcodec_receive_frame failed %d\n", ret);
2594   }
2595   av_packet_unref(&ipkt);
2596   av_frame_free(&ipic);
2597   avcodec_free_context(&ctx);
2598   
2599   if (ilaced < 0) {
2600   fprintf(stderr, "warning bdwrite uses field into from stream \n", st->codecpar->field_order);
2601   switch(st->codecpar->field_order) {
2602   case AV_FIELD_TT:
2603   case AV_FIELD_TB:   
2604   case AV_FIELD_BB:    
2605   case AV_FIELD_BT:      
2606      return 1;
2607   case AV_FIELD_PROGRESSIVE:   
2608     return 0;
2609   default:
2610    return -1;
2611    }
2612   }
2613   
2614   return ilaced;
2615 }
2616
2617 int media_info::scan()
2618 {
2619   struct stat st;
2620   if( stat(filename, &st) ) return 1;
2621   file_size = st.st_size;
2622
2623   AVFormatContext *fmt_ctx = 0;
2624   AVDictionary *fopts = 0;
2625   av_dict_set(&fopts, "formatprobesize", "5000000", 0);
2626   av_dict_set(&fopts, "scan_all_pmts", "1", 0);
2627   av_dict_set(&fopts, "threads", "auto", 0);
2628   int ret = avformat_open_input(&fmt_ctx, filename, NULL, &fopts);
2629   av_dict_free(&fopts);
2630   if( ret < 0 ) return ret;
2631   ret = avformat_find_stream_info(fmt_ctx, NULL);
2632
2633   bit_rate = fmt_ctx->bit_rate;
2634
2635   int ep_pid = -1;
2636   for( int i=0; ret>=0 && i<(int)fmt_ctx->nb_streams; ++i ) {
2637     AVStream *st = fmt_ctx->streams[i];
2638     AVMediaType type = st->codecpar->codec_type;
2639     switch( type ) {
2640     case AVMEDIA_TYPE_VIDEO: break;
2641     case AVMEDIA_TYPE_AUDIO: break;
2642     case AVMEDIA_TYPE_SUBTITLE: break;
2643     default: continue;
2644     }
2645     stream *s = new stream(type, i);
2646     s->pid = st->id;
2647     AVCodecID codec_id = st->codecpar->codec_id;
2648 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(59,16,100)
2649     const AVCodec *decoder = avcodec_find_decoder(codec_id);
2650 #endif
2651 #if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(58,134,100)
2652     AVCodec *decoder = avcodec_find_decoder(codec_id);
2653 #endif
2654
2655     s->ctx = avcodec_alloc_context3(decoder);
2656     if( !s->ctx ) {
2657       fprintf(stderr, "avcodec_alloc_context failed\n");
2658       continue;
2659     }
2660     switch( type ) {
2661     case AVMEDIA_TYPE_VIDEO: {
2662       if( ep_pid < 0 ) ep_pid = st->id;
2663       s->coding_type = bd_coding_type(codec_id);
2664       int ilace = field_probe(fmt_ctx, st);
2665       if( ilace < 0 ) {
2666         fprintf(stderr, "interlace probe failed\n");
2667         exit(1);
2668       }
2669       s->format = bd_video_format(st->codecpar->width, st->codecpar->height, ilace);
2670       AVRational framerate = av_guess_frame_rate(fmt_ctx, st, 0);
2671       s->rate = bd_video_rate(!framerate.den ? 0 : (double)framerate.num / framerate.den);
2672       s->aspect = bd_aspect_ratio(st->codecpar->width, st->codecpar->height,
2673                 !st->sample_aspect_ratio.num || !st->sample_aspect_ratio.den ? 1. :
2674                  (double)st->sample_aspect_ratio.num / st->sample_aspect_ratio.den);
2675       break; }
2676     case AVMEDIA_TYPE_AUDIO: {
2677       s->coding_type = bd_coding_type(codec_id);
2678       s->format = bd_audio_format(st->codecpar->channels);
2679       s->rate = bd_audio_rate(st->codecpar->sample_rate);
2680       strcpy((char*)s->lang, "eng");
2681       break; }
2682     case AVMEDIA_TYPE_SUBTITLE: {
2683       s->coding_type = bd_coding_type(codec_id);
2684       AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", 0, 0);
2685       strncpy((char*)s->lang, lang ? lang->value : "und", sizeof(s->lang));
2686       break; }
2687     default:
2688       break;
2689     }
2690     if( bit_rate > 0 && st->duration == AV_NOPTS_VALUE &&
2691         st->time_base.num < INT64_MAX / bit_rate ) {
2692       st->duration = av_rescale(8*file_size, st->time_base.den,
2693           bit_rate * (int64_t) st->time_base.num);
2694     }
2695     s->duration = av_rescale_q(st->duration, st->time_base, clk45k);
2696     streams.append(s);
2697
2698     AVDictionary *copts = 0;
2699     ret = avcodec_open2(s->ctx, decoder, &copts);
2700   }
2701   if( ep_pid < 0 )
2702     ep_pid = fmt_ctx->nb_streams > 0 ? fmt_ctx->streams[0]->id : 0;
2703
2704   int npgm = fmt_ctx->nb_programs;
2705   if( npgm < 1 ) {
2706     program *pgm = new program(-1, 1);
2707     pgm->ep_pid = ep_pid;
2708     pgm->pmt_pid = 0x1000;
2709     pgm->pcr_pid = 0x1001;
2710     pgm->duration = 0;
2711     for( int jj=0; jj<streams.size(); ++jj ) {
2712       AVStream *st = fmt_ctx->streams[jj];
2713       AVMediaType type = st->codecpar->codec_type;
2714       switch( type ) {
2715       case AVMEDIA_TYPE_VIDEO:
2716       case AVMEDIA_TYPE_AUDIO:
2717         break;
2718       default:
2719         continue;
2720       }
2721       pgm->strm_idx.append(jj);
2722       if( !pgm->duration || st->duration < pgm->duration )
2723         pgm->duration = av_rescale_q(st->duration, st->time_base, clk45k);
2724     }
2725     programs.append(pgm);
2726   }
2727
2728   for( int ii=0; ii<npgm; ++ii ) {
2729     AVProgram *pgrm = fmt_ctx->programs[ii];
2730     program *pgm = new program(ii, pgrm->id);
2731     pgm->pmt_pid = pgrm->pmt_pid;
2732     pgm->pcr_pid = pgrm->pcr_pid;
2733     pgm->duration = 0;
2734     ep_pid = -1;
2735     for( int jj=0; jj<(int)pgrm->nb_stream_indexes; ++jj ) {
2736       int av_idx = pgrm->stream_index[jj];
2737       AVStream *st = fmt_ctx->streams[av_idx];
2738       AVMediaType type = st->codecpar->codec_type;
2739       switch( type ) {
2740       case AVMEDIA_TYPE_VIDEO:
2741         if( ep_pid < 0 ) ep_pid = st->id;
2742         break;
2743       case AVMEDIA_TYPE_AUDIO:
2744       case AVMEDIA_TYPE_SUBTITLE:
2745         break;
2746       default:
2747         continue;
2748       }
2749       int sidx = streams.size();
2750       while( --sidx>=0 && streams[sidx]->av_idx!=av_idx );
2751       if( sidx < 0 ) {
2752         fprintf(stderr, "bad stream idx %d in pgm %d\n",av_idx, ii);
2753         continue;
2754       }
2755       if( !pgm->duration || st->duration < pgm->duration )
2756         pgm->duration = av_rescale_q(st->duration, st->time_base, clk45k);
2757       pgm->strm_idx.append(sidx);
2758     }
2759     if( ep_pid < 0 ) {
2760       AVProgram *pgrm = fmt_ctx->programs[0];
2761       ep_pid = pgrm->nb_stream_indexes > 0 ?
2762           fmt_ctx->streams[pgrm->stream_index[0]]->id : 0;
2763     }
2764     pgm->ep_pid = ep_pid;
2765     programs.append(pgm);
2766   }
2767
2768   if( ret >= 0 )
2769     ret = scan(fmt_ctx);
2770
2771   for( int i=0; i<(int)streams.size(); ++i )
2772     avcodec_close(streams[i]->ctx);
2773   avformat_close_input(&fmt_ctx);
2774
2775   return ret;
2776 }
2777
2778 int media_info::scan(AVFormatContext *fmt_ctx)
2779 {
2780   int ret = 0;
2781   AVPacket ipkt;
2782   av_init_packet(&ipkt);
2783 #if 1
2784 // zero pts at pos zero
2785   for( int i=0; i<programs.size(); ++i ) {
2786     program *p = programs[i];
2787     for( int j=0; j<p->strm_idx.size(); ++j ) {
2788       stream *sp = streams[p->strm_idx[j]];
2789       sp->last_pts = 0;
2790       AVStream *st = fmt_ctx->streams[sp->av_idx];
2791       p->add_label(0, 0, 0, st->id);
2792     }
2793   }
2794 #endif
2795   for( int64_t count=0; ret>=0; ++count ) {
2796     av_packet_unref(&ipkt);
2797     ipkt.data = 0; ipkt.size = 0;
2798
2799     ret = av_read_frame(fmt_ctx, &ipkt);
2800     if( ret < 0 ) {
2801       if( ret == AVERROR_EOF ) break;
2802       ret = 0;
2803       continue;
2804     }
2805     if( !ipkt.data ) continue;
2806     if( (ipkt.flags & AV_PKT_FLAG_CORRUPT) ) continue;
2807     if( ipkt.pts == AV_NOPTS_VALUE ) continue;
2808     int i = ipkt.stream_index;
2809     if( i < 0 || i >= streams.size() ) continue;
2810
2811     stream *sp = 0;
2812     program *pgm = 0;
2813     for( int ii=0; !pgm && ii<programs.size(); ++ii ) {
2814       program *p = programs[ii];
2815       for( int jj=0; jj<p->strm_idx.size(); ++jj ) {
2816         sp = streams[p->strm_idx[jj]];
2817         if( sp->av_idx == i ) { pgm = p;  break; }
2818       }
2819     }
2820     if( !pgm ) continue;
2821     AVStream *st = fmt_ctx->streams[i];
2822     if( pgm->ep_pid != st->id ) continue;
2823     int64_t pts45k = av_rescale_q(ipkt.pts, st->time_base, clk45k);
2824     if( sp->start_pts > pts45k ) sp->start_pts = pts45k;
2825     if( sp->end_pts < pts45k ) sp->end_pts = pts45k;
2826     if( pgm->start_time > pts45k ) pgm->start_time = pts45k;
2827     if( pgm->end_time < pts45k ) pgm->end_time = pts45k;
2828
2829     if( !(ipkt.flags & AV_PKT_FLAG_KEY) ) continue;
2830
2831     if( sp->last_pts != pts45k ) {
2832       sp->last_pts = pts45k;
2833       pgm->add_label(count, ipkt.pos, pts45k, st->id);
2834     }
2835   }
2836
2837   for( int ii=0; ii<programs.size(); ++ii ) {
2838     program *pgm = programs[ii];
2839     if( pgm->end_time > pgm->start_time )
2840       pgm->duration = pgm->end_time - pgm->start_time;
2841   }
2842
2843   return ret != AVERROR_EOF ? -1 : 0;
2844 }
2845
2846 void
2847 Media::add_movie(uint32_t *ops, int n)
2848 {
2849   movie_obj *mp = new movie_obj();
2850   mp->resume_intention_flag = 1;
2851   uint32_t *eop = ops + n/sizeof(*ops);
2852   while( ops < eop ) {
2853     command_obj *cmd = new command_obj();
2854     cmd->cmd = htobe32(*ops++);
2855     cmd->dst = *ops++;
2856     cmd->src = *ops++;
2857     mp->cmds.append(cmd);
2858   }
2859   mov.movies.append(mp);
2860 }
2861
2862 int
2863 Media::compose(int ch_interval)
2864 {
2865 // movie
2866   bs.init();
2867
2868 // top menu
2869   int top_menu_obj = mov.movies.size();
2870   movie_obj *mp = new movie_obj();
2871   mp->resume_intention_flag = 1;
2872   command_obj *cmd = new command_obj();
2873   cmd->cmd = htobe32(0x21810000); cmd->dst = 1; cmd->src = 0;
2874   mp->cmds.append(cmd);  // JUMP_TITLE 1
2875   mov.movies.append(mp);
2876
2877 // titles
2878   for( int ii=0; ii<size(); ++ii ) {
2879     mp = new movie_obj();
2880     mp->resume_intention_flag = 1;
2881     cmd = new command_obj();
2882     cmd->cmd = htobe32(0x22800000); cmd->dst = ii; cmd->src = 0;
2883     mp->cmds.append(cmd);  // PLAY_PL   ii
2884     cmd = new command_obj();
2885     cmd->cmd = htobe32(0x00020000); cmd->dst = 0; cmd->src = 0;
2886     mp->cmds.append(cmd);
2887     mov.movies.append(mp); // BREAK
2888   }
2889
2890 // first play
2891   int first_play_obj = mov.movies.size();
2892   mp = new movie_obj();
2893   mp->resume_intention_flag = 1;
2894   cmd = new command_obj();
2895   cmd->cmd = htobe32(0x21810000); cmd->dst = 0; cmd->src = 0;
2896   mp->cmds.append(cmd);  // JUMP_TITLE 0 ; top menu
2897   mov.movies.append(mp);
2898
2899 // index
2900   bs.init();
2901   idx.first_play.set_hdmv(first_play_obj, pb_typ_iactv);
2902   idx.top_menu.set_hdmv(top_menu_obj, pb_typ_iactv);
2903
2904   title_obj *tp = 0;
2905 // clips
2906   for( int ii=0; ii<size(); ++ii ) {
2907     if( !tp ) {
2908       tp = new title_obj();
2909       tp->set_hdmv(idx.titles.size()+1, pb_typ_movie);
2910       idx.titles.append(tp);
2911     }
2912     bs.init();
2913     media_info *ip = get(ii);
2914 // clip program, if specified
2915     int pidx = ip->programs.size();
2916     while( --pidx>=0 && ip->programs[pidx]->pid != ip->pgm_pid );
2917     if( pidx < 0 ) pidx = 0;
2918     ip->pidx = pidx;
2919     ip->pgm_pid = ip->prog()->pid;
2920
2921     clpi_cl *cp = new clpi_cl();
2922     cp->clip.clip_stream_type = 1;
2923     cp->clip.application_type = BLURAY_APP_TYPE_MAIN_MOVIE;
2924     cp->clip.ts_recording_rate = ip->bit_rate;
2925     uint32_t ts_pkt_count = ip->file_size / BLURAY_TS_PKTSZ;
2926     cp->clip.num_source_packets = ts_pkt_count;
2927     cp->clip.ts_type_info.validity = 0x80;
2928     strcpy(cp->clip.ts_type_info.format_id, "HDMV");
2929     cp->cpi.type = 1;
2930
2931     for( int jj=0; jj<ip->programs.size(); ++jj ) {
2932       program *pgm = ip->programs[jj];
2933       clpi_prog *p = new clpi_prog(pgm->pmt_pid);
2934       for( int kk=0; kk<pgm->strm_idx.size(); ++kk ) {
2935         int k = pgm->strm_idx[kk];
2936         stream *sp = ip->streams[k];
2937         clpi_prog_stream *s = new clpi_prog_stream();
2938         s->pid = sp->pid;
2939         s->coding_type = sp->coding_type;
2940         s->format = sp->format;
2941 //use unspecified (0)
2942 //      if( !idx.video_format ) idx.video_format = s->format;
2943         s->rate = sp->rate;
2944 //      if( !idx.frame_rate ) idx.frame_rate = s->rate;
2945         switch( sp->type ) {
2946         case AVMEDIA_TYPE_VIDEO:
2947           s->aspect = sp->aspect;
2948           break;
2949         case AVMEDIA_TYPE_AUDIO:
2950         case AVMEDIA_TYPE_SUBTITLE:
2951           memcpy(s->lang,sp->lang,sizeof(s->lang));
2952           break;
2953         default:
2954           break;
2955         }
2956         p->streams.append(s);
2957       }
2958       clpi_ep_map_entry *map = new clpi_ep_map_entry(pgm->ep_pid);
2959       map->ep_stream_type = 1;
2960       pgm->build_toc(map);
2961       cp->cpi.append(map);
2962       cp->programs.append(p);
2963
2964       clpi_atc_seq *atc_seq = new clpi_atc_seq();
2965       clpi_stc_seq *stc_seq = new clpi_stc_seq();
2966       stc_seq->pcr_pid = pgm->pcr_pid;
2967       stc_seq->presentation_start_time = pgm->start_time;
2968       stc_seq->presentation_end_time = pgm->end_time;
2969       atc_seq->stc_seq.append(stc_seq);
2970       cp->sequences.append(atc_seq);
2971     }
2972
2973     cl.append(cp);
2974     tp->last = ii;
2975     if( ip->brk ) tp = 0;
2976   }
2977
2978 // playlists, one per title
2979 //   one playitem per media clip
2980   int clip_id = 0;
2981   for( int ii=0; ii<idx.titles.size(); ++ii ) {
2982     bs.init();
2983     media_info *ip = get(clip_id);
2984     program *pgm = ip->prog();
2985     mpls_pl *pp = new mpls_pl();
2986     pp->app_info.playback_type = BLURAY_PLAYBACK_TYPE_SEQUENTIAL;
2987 //  pp->app_info.uo_mask.xxx = 1;
2988     int last = idx.titles[ii]->last;
2989     for( ; clip_id<=last; ++clip_id ) {
2990       ip = get(clip_id);
2991       pgm = ip->prog();
2992       mpls_pi *pi = new mpls_pi();
2993       pi->connection_condition = 1; // seamless
2994 //    pi->uo_mask.xxx = 1;
2995       pi->in_time = pgm->start_time;
2996       pi->out_time = pgm->end_time;
2997       if( ip->still )
2998         pi->still_mode = BLURAY_STILL_INFINITE;
2999       int64_t end_time = pgm->start_time + pgm->duration;
3000       if( pi->out_time < end_time ) pi->out_time = end_time;
3001       mpls_clip *cp = new mpls_clip();
3002       sprintf(cp->clip_id,"%05d", clip_id);
3003       pi->clip.append(cp);
3004       for( int kk=0; kk<ip->streams.size(); ++kk ) {
3005         stream *sp = ip->streams[kk];
3006         switch( sp->type ) {
3007         case AVMEDIA_TYPE_VIDEO: break;
3008         case AVMEDIA_TYPE_AUDIO: break;
3009         case AVMEDIA_TYPE_SUBTITLE: break;
3010         default: continue;
3011         }
3012         mpls_stream *ps = new mpls_stream();
3013         ps->pid = sp->pid;
3014         ps->stream_type = BLURAY_PG_TEXTST_STREAM;
3015         ps->coding_type = sp->coding_type;
3016         ps->format = sp->format;
3017         ps->rate = sp->rate;
3018         switch( sp->type ) {
3019         case AVMEDIA_TYPE_VIDEO:
3020           pi->stn.video.append(ps);
3021           break;
3022         case AVMEDIA_TYPE_AUDIO:
3023           memcpy(ps->lang, sp->lang, sizeof(ps->lang));
3024           pi->stn.audio.append(ps);
3025           break;
3026         case AVMEDIA_TYPE_SUBTITLE:
3027           memcpy(ps->lang, sp->lang, sizeof(ps->lang));
3028           pi->stn.pg.append(ps);
3029           break;
3030         default:
3031           break;
3032         }
3033       }
3034       pp->play_item.append(pi);
3035     }
3036 // chapter marks every ch_duration seconds * 45Kticks, default 5 min
3037     int PCR_FREQ = 45000;
3038     if (ch_interval == 0)
3039     ch_interval = 60*5;
3040     int64_t ch_duration = PCR_FREQ * ch_interval;
3041     int64_t mrktm = ch_duration;
3042     int64_t plytm = 0;
3043     int pmark = 0, pitem = 0;
3044     mpls_pi *pi = pp->play_item[pitem];
3045     mpls_plm *pm = new mpls_plm();
3046     pm->mark_id = pmark++;
3047     pm->mark_type = BLURAY_MARK_TYPE_ENTRY;
3048     pm->play_item_ref = pitem;
3049     pm->time = pi->in_time;
3050     pm->entry_es_pid = 0;
3051     pp->play_mark.append(pm);
3052     for( int jj=0; jj < pp->play_item.size(); ++jj ) {
3053       pitem = jj;
3054       pi = pp->play_item[pitem];
3055       int64_t pi_duration = pi->out_time - pi->in_time;
3056       int64_t endtm = plytm + pi_duration;
3057       while( mrktm < endtm ) {
3058         pm = new mpls_plm();
3059         pm->mark_id = pmark++;
3060         pm->mark_type = BLURAY_MARK_TYPE_ENTRY;
3061         pm->play_item_ref = pitem;
3062         pm->time = pi->in_time + mrktm - plytm;
3063         pm->entry_es_pid = 0;
3064         pp->play_mark.append(pm);
3065         mrktm += ch_duration;
3066       }
3067       plytm = endtm;
3068     }
3069     pm = new mpls_plm();
3070     pm->mark_id = pmark;
3071     pm->mark_type = BLURAY_MARK_TYPE_ENTRY;
3072     pm->play_item_ref = pitem;
3073     pm->time = pi->out_time;
3074     pm->entry_es_pid = 0;
3075     pp->play_mark.append(pm);
3076
3077     pl.append(pp);
3078   }
3079   return 0;
3080 }
3081
3082 int Media::
3083 bd_path(const char *bp, const char *fmt, va_list ap)
3084 {
3085   int n = sizeof(filename)-1;
3086   char *cp = filename;
3087   const char *pp = path;
3088   while( n>0 && (*cp=*pp)!=0 ) { --n;  ++cp;  ++pp; }
3089   while( n>0 && (*cp=*bp)!=0 ) { --n;  ++cp;  ++bp; }
3090   n -= vsnprintf(cp, n, fmt, ap);
3091   va_end(ap);
3092   return n > 0 ? 0 : 1;
3093 }
3094
3095 int Media::
3096 bd_copy(const char *ifn, const char *fmt, ...)
3097 {
3098   int bfrsz = 0x40000, ret = 1;
3099   char bfr[bfrsz];
3100   FILE *ifp = fopen(ifn,"r");
3101   if( ifp ) {
3102     va_list ap;
3103     va_start(ap, fmt);
3104     if( bd_path("/BDMV/", fmt, ap) ) return 1;
3105     va_end(ap);
3106     FILE *ofp = fopen(filename,"w");
3107     if( ofp ) {
3108       setvbuf(ifp, 0, _IOFBF, 0x80000);
3109       setvbuf(ofp, 0, _IOFBF, 0x80000);
3110       ret = 0;
3111       int n = bfrsz;
3112       while( !ret && n >= bfrsz ) {
3113         n = fread(bfr,1,bfrsz,ifp);
3114         if( n > 0 && (int)fwrite(bfr,1,n,ofp) != n ) {
3115           fprintf(stderr, "cant write: %s\n",filename);
3116           ret = 1;
3117         }
3118       }
3119       if( ferror(ifp) ) {
3120         fprintf(stderr, "read error: %s = %m\n",ifn);
3121         ret = 1;
3122       }
3123       if( ferror(ofp) ) {
3124         fprintf(stderr, "write error: %s = %m\n",filename);
3125         ret = 1;
3126       }
3127       if( fclose(ofp) ) {
3128         fprintf(stderr, "close error: %s = %m\n",filename);
3129         ret = 1;
3130       }
3131     }
3132     fclose(ifp);
3133   }
3134   if( ret )
3135     fprintf(stderr, "cant copy clip %s\n",ifn);
3136   return ret;
3137 }
3138
3139 int Media::
3140 bd_open(const char *fmt, ...)
3141 {
3142   bs.init();
3143   if( !path ) return 0;
3144   va_list ap;
3145   va_start(ap, fmt);
3146   if( bd_path("/BDMV/", fmt, ap) ) return 1;
3147   va_end(ap);
3148   if( bs.open(filename) ) {
3149     fprintf(stderr, "cant open file %s\n",filename);
3150     return 1;
3151   }
3152   return 0;
3153 }
3154
3155 int Media::
3156 bd_backup(const char *fmt, ...)
3157 {
3158   bs.close();
3159   if( !path ) return 0;
3160   int n, ret = 1;
3161   char bfr[0x10000];
3162   FILE *ifp = fopen(filename,"r");
3163   if( ifp ) {
3164     va_list ap;
3165     va_start(ap, fmt);
3166     if( bd_path("/BDMV/BACKUP/", fmt, ap) ) return 1;
3167     va_end(ap);
3168     FILE *ofp = fopen(filename,"w");
3169     if( ofp ) {
3170       while( (n=fread(bfr,1,sizeof(bfr),ifp)) > 0 ) fwrite(bfr,1,n,ofp);
3171       fclose(ofp);
3172       ret = 0;
3173     }
3174     fclose(ifp);
3175   }
3176   if( ret )
3177     fprintf(stderr, "cant backup %s\n",filename);
3178   return ret;
3179 }
3180
3181 int Media::write(char *fn)
3182 {
3183   this->path = fn;
3184 // index
3185   if( bd_open("index.bdmv") ) return 1;
3186   if( idx.write() ) return 1;
3187   if( bd_backup("index.bdmv") ) return 1;
3188 // movie
3189   if( bd_open("MovieObject.bdmv") ) return 1;
3190   if( mov.write() ) return 1;
3191   if( bd_backup("MovieObject.bdmv") ) return 1;
3192 // clips
3193   for( int ii=0; ii<cl.size(); ++ii ) {
3194     if( bd_open("CLIPINF/%05d.clpi", ii) ) return 1;
3195     if( cl[ii]->write() ) return 1;
3196     if( bd_backup("CLIPINF/%05d.clpi", ii) ) return 1;
3197   }
3198 // playlists
3199   for( int ii=0; ii<pl.size(); ++ii ) {
3200     if( bd_open("PLAYLIST/%05d.mpls", ii) ) return 1;
3201     if( pl[ii]->write() ) return 1;
3202     if( bd_backup("PLAYLIST/%05d.mpls", ii) ) return 1;
3203   }
3204   return 0;
3205 }
3206
3207 int
3208 main(int ac, char **av)
3209 {
3210   char *path = av[1];
3211   
3212   av_log_set_level(AV_LOG_FATAL);
3213   //av_log_set_level(AV_LOG_VERBOSE);
3214   //av_log_set_level(AV_LOG_DEBUG);
3215   Media media;
3216   media_info *mp = 0;
3217   int start  = 0, chapter_every_n_sec = 0;
3218
3219   int opt = getopt(ac, av, "c:");
3220   if (opt == 'c') {
3221   chapter_every_n_sec = atoi(optarg); start = 4;
3222   path = av[3]; printf("Chapter interval: %i \n", chapter_every_n_sec );}
3223   else
3224   start = 2;
3225   if( mkbdmv(path) ) return 1;
3226   for( int ii=start; ii<ac; ++ii ) {
3227     char *ap = av[ii];
3228     // any dash seq followed by number sets curr title pgm_pid
3229     // single dash only sets title pgm_pid
3230     // double dash ends curr title, starts a new title
3231     // triple dash ends curr title as infinite still
3232     if( *ap == '-' ) {
3233       if( !mp ) continue;
3234       if( *++ap == '-' ) {
3235         mp->brk = 1;
3236         if( *++ap == '-' ) { ++ap;  mp->still = 1; }
3237       }
3238       if( *ap >= '0' && *ap <= '9' )
3239         mp->pgm_pid = strtoul(ap,&ap,0);
3240       if( mp->brk ) mp = 0;
3241       if( !ap || *ap ) {
3242         fprintf(stderr, "err arg %d: %s\n",ii,av[ii]);
3243         return 1;
3244       }
3245       continue;
3246     }
3247     mp = new media_info(av[ii]);
3248     media.append(mp);
3249     if( mp->scan() ) {
3250       fprintf(stderr, "cant scan media: %s\n", av[ii]);
3251       return 1;
3252     }
3253   }
3254
3255   if( mp ) mp->brk = 1;
3256
3257   if( media.compose(chapter_every_n_sec) ) {
3258     fprintf(stderr, "cant compose media\n");
3259     return 1;
3260   }
3261   if( media.write(0) ) {
3262     fprintf(stderr, "cant prepare media\n");
3263     return 1;
3264   }
3265   if( media.write(path) ) {
3266     fprintf(stderr, "cant write media\n");
3267     return 1;
3268   }
3269
3270   for( int ii=0; ii<media.size(); ++ii )
3271     if( media.bd_copy(media[ii]->filename, "STREAM/%05d.m2ts", ii) )
3272       return 1;
3273
3274   return 0;
3275 }
3276