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