add missing ffmpeg encoder flush, bdwrite leaks + fixes
[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     clip.remove_all_objects();
724   }
725 };
726
727 class _mpls_plm {
728 public:
729   uint8_t mark_id;
730   uint8_t mark_type;
731   uint16_t play_item_ref;
732   uint32_t time;
733   uint16_t entry_es_pid;
734   uint32_t duration;
735
736   _mpls_plm() { memset(this, 0, sizeof(*this)); }
737   ~_mpls_plm() {}
738 };
739
740 class mpls_plm : public _mpls_plm {
741 public:
742   int write();
743
744   mpls_plm() {}
745   ~mpls_plm() {}
746 };
747
748 class _mpls_ai {
749 public:
750   uint8_t playback_type;
751   uint16_t playback_count;
752   uint8_t random_access_flag;
753   uint8_t audio_mix_flag;
754   uint8_t lossless_bypass_flag;
755
756   _mpls_ai() { memset(this, 0, sizeof(*this)); }
757   ~_mpls_ai() {}
758 };
759
760 class mpls_ai : public bs_length, public _mpls_ai {
761 public:
762   bd_uo_mask uo_mask;
763   int write();
764
765   mpls_ai() {}
766   ~mpls_ai() {}
767 };
768
769 class _mpls_sub_pi {
770 public:
771   uint8_t connection_condition;
772   uint8_t is_multi_clip;
773   uint32_t in_time;
774   uint32_t out_time;
775   uint16_t sync_play_item_id;
776   uint32_t sync_pts;
777
778   _mpls_sub_pi() { memset(this, 0, sizeof(*this)); }
779   ~_mpls_sub_pi() {}
780 };
781
782 class mpls_sub_pi : public bs_length, public _mpls_sub_pi {
783 public:
784   ArrayList<mpls_clip *> clip;
785   int write();
786
787   mpls_sub_pi() {}
788   ~mpls_sub_pi() {
789     clip.remove_all_objects();
790   }
791 };
792
793 class _mpls_sub {
794 public:
795   uint8_t type;
796   uint8_t is_repeat;
797
798   _mpls_sub() { memset(this, 0, sizeof(*this)); }
799   ~_mpls_sub() {}
800 };
801
802 class mpls_sub : public bs_length, public _mpls_sub {
803 public:
804   ArrayList<mpls_sub_pi *> sub_play_item;
805
806   int write();
807   mpls_sub() {}
808   ~mpls_sub() {
809    sub_play_item.remove_all_objects();
810   }
811 };
812
813 class _mpls_pip_data {
814 public:
815   uint32_t time;
816   uint16_t xpos;
817   uint16_t ypos;
818   uint8_t scale_factor;
819
820   _mpls_pip_data() { memset(this, 0, sizeof(*this)); }
821   ~_mpls_pip_data() {}
822 };
823
824 class mpls_pip_data : public _mpls_pip_data {
825 public:
826   int write();
827
828   mpls_pip_data() {}
829   ~mpls_pip_data() {}
830 };
831
832 class _mpls_pip_metadata {
833 public:
834   uint16_t clip_ref;
835   uint8_t secondary_video_ref;
836   uint8_t timeline_type;
837   uint8_t luma_key_flag;
838   uint8_t upper_limit_luma_key;
839   uint8_t trick_play_flag;
840
841   _mpls_pip_metadata() { memset(this, 0, sizeof(*this)); }
842   ~_mpls_pip_metadata() {}
843 };
844
845 class mpls_pip_metadata : public _mpls_pip_metadata {
846 public:
847   ArrayList<mpls_pip_data *> data;
848
849   int write(uint32_t start_address);
850   mpls_pip_metadata() {}
851   ~mpls_pip_metadata() {
852     data.remove_all_objects();
853   }
854 };
855
856 class _mpls_pl {
857 public:
858   uint32_t list_pos;
859   uint32_t mark_pos;
860   uint32_t ext_pos;
861
862   _mpls_pl() { memset(this, 0, sizeof(*this)); }
863   ~_mpls_pl() {}
864 };
865
866 class mpls_pl : public _mpls_pl {
867 public:
868   int sig;
869   bs_length play, mark, subx, pipm;
870   mpls_ai app_info;
871   ArrayList<mpls_pi *> play_item;
872   ArrayList<mpls_sub *> sub_path;
873   ArrayList<mpls_plm *> play_mark;
874   // extension data (profile 5, version 2.4)
875   ArrayList<mpls_sub *> ext_sub_path;
876   // extension data (Picture-In-Picture metadata)
877   ArrayList<mpls_pip_metadata *> ext_pip_data;
878
879   int write_header();
880   int write_playlist();
881   int write_playlistmark();
882   int write_subpath_extension();
883   int write_pip_metadata_extension();
884   int write();
885
886   mpls_pl() { sig = 1; }
887   ~mpls_pl() {
888     play_item.remove_all_objects();
889     sub_path.remove_all_objects();
890     play_mark.remove_all_objects();
891     ext_sub_path.remove_all_objects();
892     ext_pip_data.remove_all_objects();
893   }
894 };
895
896 class _clpi_cl {
897 public:
898   uint32_t sequence_info_start_addr;
899   uint32_t program_info_start_addr;
900   uint32_t cpi_start_addr;
901   uint32_t clip_mark_start_addr;
902   uint32_t ext_data_start_addr;
903
904   _clpi_cl() { memset(this, 0, sizeof(*this)); }
905   ~_clpi_cl() {}
906 };
907
908 class clpi_cl : public _clpi_cl {
909 public:
910   int sig;
911   clpi_clip_info clip;
912   clpi_sequences sequences;
913   clpi_programs programs;
914   clpi_cpi cpi;
915   clpi_extents extents;
916   clpi_programs programs_ss;
917   clpi_cpi cpi_ss;
918
919   int write_header();
920   int write();
921
922   int write_clpi_extension(int id1, int id2, void *handle);
923   int write_mpls_extension(int id1, int id2, void *handle);
924
925   clpi_cl() { sig = 1; }
926   ~clpi_cl() {}
927 };
928
929 class command_obj {
930 public:
931   union {
932     uint32_t cmd;
933     struct {
934       uint32_t sub_grp:3;       /* command sub-group */
935       uint32_t grp:2;           /* command group */
936       uint32_t op_cnt:3;        /* operand count */
937       uint32_t branch_opt:4;    /* branch option */
938       uint32_t rsvd1:2;
939       uint32_t imm_op2:1;       /* I-flag for operand 2 */
940       uint32_t imm_op1:1;       /* I-flag for operand 1 */
941       uint32_t cmp_opt:4;       /* compare option */
942       uint32_t rsvd2:4;
943       uint32_t set_opt:5;       /* set option */
944       uint32_t rsvd3:3;
945     };
946   };
947   uint32_t dst;
948   uint32_t src;
949
950   command_obj() { cmd = dst = src = 0; }
951   ~command_obj() {}
952 };
953
954 class _movie_obj {
955 public:
956   int resume_intention_flag;
957   int menu_call_mask;
958   int title_search_mask;
959
960   _movie_obj() { memset(this, 0, sizeof(*this)); }
961   ~_movie_obj() {}
962 };
963
964 class movie_obj : public _movie_obj {
965 public:
966   ArrayList<command_obj *> cmds;
967
968   movie_obj() {}
969   ~movie_obj() {
970     cmds.remove_all_objects();
971   }
972 };
973
974 class movie_file : public bs_length {
975 public:
976   int sig;
977   ArrayList<movie_obj *> movies;
978
979   movie_file() { sig = 1; }
980   ~movie_file() {
981     movies.remove_all_objects();
982   }
983
984   int write();
985 };
986
987 class _pb_obj {
988 public:
989   int obj_typ;
990   int pb_typ;
991   int hdmv_id;
992
993   _pb_obj() { memset(this, 0, sizeof(*this)); }
994   ~_pb_obj() {}
995 };
996
997 class pb_obj : public _pb_obj {
998 public:
999   int last;
1000   char *bdj_name;
1001   void write_obj();
1002
1003   pb_obj() {
1004     last = 0;
1005     bdj_name = 0;
1006   }
1007   ~pb_obj() {
1008     delete [] bdj_name;
1009   }
1010
1011   void set_hdmv(int id, int pt);
1012   void set_bdj(char *nm, int pt);
1013   void write_hdmv_obj(int id_ref);
1014   void write_bdj_obj(char *name);
1015 };
1016
1017 class _title_obj {
1018 public:
1019   int acc_typ;
1020   _title_obj() { acc_typ = 0; }
1021   ~_title_obj() {}
1022 };
1023
1024 class title_obj : public pb_obj, public _title_obj {
1025 public:
1026   title_obj() {}
1027   ~title_obj() {}
1028
1029   void write_obj();
1030 };
1031
1032 class _index_file {
1033 public:
1034   int sig;
1035   int initial_output_mode_preference;
1036   int content_exist_flag;
1037   int video_format;
1038   int frame_rate;
1039
1040   _index_file() { memset(this, 0, sizeof(*this)); }
1041   ~_index_file() {}
1042 };
1043
1044 class index_file : public bs_length, public _index_file {
1045 public:
1046   ArrayList<title_obj *> titles;
1047   pb_obj first_play;
1048   pb_obj top_menu;
1049   char user_data[32];
1050   bs_length exten, appinf;
1051
1052   void write_hdmv_obj(int hdmv_typ, int id_ref);
1053   void write_bdj_obj(int bdj_typ, char *name);
1054   void write_pb_obj(pb_obj * pb);
1055   int write();
1056
1057   index_file() {
1058     sig = 1;
1059     memset(user_data, 0, sizeof(user_data));
1060   }
1061   ~index_file() {
1062     titles.remove_all_objects();
1063   }
1064 };
1065
1066 class _bdid {
1067 public:
1068   uint32_t data_start;
1069   uint32_t extension_data_start;
1070   char org_id[4];
1071   char disc_id[16];
1072
1073   _bdid() { memset(this, 0, sizeof(*this)); }
1074   ~_bdid() {}
1075 };
1076
1077 class bdid : public _bdid {
1078 public:
1079   int sig;
1080   int write();
1081
1082   bdid() { sig = 1; }
1083   ~bdid() {}
1084 };
1085
1086 class stream : public bd_stream_info {
1087 public:
1088   int av_idx;
1089   AVMediaType type;
1090   AVCodecID codec_id;
1091   int64_t start_pts;
1092   int64_t end_pts;
1093   int64_t last_pts;
1094   int64_t duration;
1095
1096   stream(AVMediaType ty, int i) {
1097     type = ty;  av_idx = i;
1098     start_pts = INT64_MAX; end_pts = INT64_MIN;
1099     last_pts = -1;
1100   }
1101   ~stream() {}
1102 };
1103
1104 class mark {
1105 public:
1106   static int cmpr(mark **, mark **);
1107   int64_t sample, pos, pts;
1108   uint32_t pkt, pid;
1109   mark(int64_t s, int64_t p, int64_t ts, uint32_t pk, int id) {
1110     sample = s;  pos = p;  pts = ts; pkt = pk;  pid = id;
1111   }
1112 };
1113
1114 int mark::cmpr(mark **a, mark **b)
1115 {
1116   mark *ap = *(mark **)a,  *bp = *(mark **)b;
1117   return ap->pts > bp->pts ? 1 : ap->pts < bp->pts ? -1 : 0;
1118 }
1119
1120 class _program {
1121 public:
1122   int pmt_pid, pcr_pid, ep_pid;
1123   int64_t start_time, end_time;
1124   int64_t duration;
1125   _program() {
1126     memset(this, 0, sizeof(*this));
1127     start_time = INT64_MAX; end_time = INT64_MIN;
1128   }
1129   ~_program() {}
1130 };
1131
1132 class program : public _program {
1133 public:
1134   int idx;
1135   uint16_t pid;
1136   ArrayList<int> strm_idx;
1137   ArrayList<mark*> marks;
1138   int64_t curr_pos;
1139   int build_toc(clpi_ep_map_entry *map);
1140   void add_label(uint32_t pk, int64_t p, int64_t ts, int id) {
1141     marks.append(new mark(curr_pos, p, ts, pk, id));
1142   }
1143
1144   program(int i, int id) { idx = i;  pid = id;  curr_pos = 0; }
1145   ~program() { marks.remove_all_objects(); }
1146 };
1147
1148 class _media_info {
1149 public:
1150   int bit_rate;
1151   int64_t file_size;
1152
1153   _media_info() {
1154     memset(this, 0, sizeof(*this));
1155   }
1156   ~_media_info() {}
1157 };
1158
1159 class media_info : public _media_info {
1160 public:
1161   static const AVRational clk45k;
1162   char filename[BCTEXTLEN];
1163   int pgm_pid;
1164   int brk, pidx, still;
1165   ArrayList<stream *> streams;
1166   ArrayList<program *> programs;
1167   program *prog()  { return programs[pidx]; }
1168
1169   media_info(const char *fn) {
1170     strcpy(filename, fn);
1171     brk = 0;  pidx = 0;  pgm_pid = -1;  still = 0;
1172   }
1173   ~media_info() {
1174     streams.remove_all_objects();
1175     programs.remove_all_objects();
1176   }
1177
1178   int scan();
1179   int scan(AVFormatContext *fmt_ctx);
1180 };
1181
1182 class Media : public ArrayList<media_info *> {
1183 public:
1184   char *path;
1185   char filename[BCTEXTLEN];
1186   int bd_path(const char *bp, const char *fmt, va_list ap);
1187   int bd_open(const char *fmt, ...);
1188   int bd_backup(const char *fmt, ...);
1189   int bd_copy(const char *ifn, const char *fmt, ...);
1190
1191   index_file idx;
1192   movie_file mov;
1193   ArrayList<clpi_cl *> cl;
1194   ArrayList<mpls_pl *> pl;
1195
1196   int compose();
1197   int write(char *fn);
1198
1199   Media() { path = 0;  filename[0] = 0; }
1200   ~Media() {
1201     remove_all_objects();
1202     cl.remove_all_objects();
1203     pl.remove_all_objects();
1204   }
1205 };
1206
1207 #endif
1208
1209 void bs_file::init()
1210 {
1211   fp = 0;
1212   reg = len = 0;
1213   fpos = fsz = 0;
1214 }
1215
1216 int
1217 bs_file::open(const char *fn)
1218 {
1219   fp = fopen(fn,"w");
1220   if( !fp ) perror(fn);
1221   return fp != 0 ? 0 : 1;
1222 }
1223
1224 void
1225 bs_file::close()
1226 {
1227   if( fp ) { fclose(fp); fp = 0; }
1228 }
1229
1230 void
1231 bs_file::write(uint32_t v, int n)
1232 {
1233   uint64_t vv = reg;
1234   vv <<= n;  vv |= v;
1235   reg = vv;  len += n;
1236   while( len >= 8 ) {
1237     len -= 8;
1238     if( fp ) fputc((vv >> len), fp);
1239     if( ++fpos > fsz ) fsz = fpos;
1240   }
1241 }
1242
1243 void
1244 bs_file::writeb(uint8_t * bp, int n)
1245 {
1246   while( --n >= 0 ) write(*bp++, 8);
1247 }
1248
1249 void
1250 bs_file::pad(int n)
1251 {
1252   while( n > 32 ) { write(0, 32);  n -= 32; }
1253   if( n > 0 ) write(0, n);
1254 }
1255
1256 void
1257 bs_file::posb(int64_t n)
1258 {
1259   if( fpos == fsz && n > fpos ) {
1260     padb(n-fpos);
1261     return;
1262   }
1263   fpos = n;
1264   if( fp ) fseek(fp, fpos, SEEK_SET);
1265 }
1266
1267 static bs_file bs;
1268
1269
1270 int
1271 movie_file::write()
1272 {
1273   // output header
1274   bs.writeb("MOBJ", 4);
1275   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1276   int movie_start = 0x0028;
1277   bs.posb(movie_start);
1278   bs_len(bs, 32);
1279   bs.write(0, 32);
1280   bs.write(movies.size(), 16);
1281
1282   for (int i = 0; i < movies.size(); ++i) {
1283     movie_obj *mov = movies[i];
1284     bs.write(mov->resume_intention_flag, 1);
1285     bs.write(mov->menu_call_mask, 1);
1286     bs.write(mov->title_search_mask, 1);
1287     bs.write(0, 13);
1288     ArrayList<command_obj *> &cmds = mov->cmds;
1289     int num_cmds = cmds.size();
1290     bs.write(num_cmds, 16);
1291     for (int j = 0; j < num_cmds; ++j) {
1292       command_obj *cmd = cmds[j];
1293       bs.write(cmd->op_cnt, 3);
1294       bs.write(cmd->grp, 2);
1295       bs.write(cmd->sub_grp, 3);
1296       bs.write(cmd->imm_op1, 1);
1297       bs.write(cmd->imm_op2, 1);
1298       bs.write(0, 2);
1299       bs.write(cmd->branch_opt, 4);
1300       bs.write(0, 4);
1301       bs.write(cmd->cmp_opt, 4);
1302       bs.write(0, 3);
1303       bs.write(cmd->set_opt, 5);
1304       //bs.write(cmd->cmd, 32);
1305       bs.write(cmd->dst, 32);
1306       bs.write(cmd->src, 32);
1307     }
1308   }
1309 //in sony AVCHD
1310 //  bs.write('l', 8);
1311 //  bs.writebcd(year, 16);
1312 //  bs.writebcd(month, 8);
1313 //  bs.writebcd(day, 8);
1314 //  bs.writebcd(hour, 8);
1315 //  bs.writebcd(min, 8);
1316 //  bs.writebcd(sec, 8);
1317   bs_end(bs);
1318   return 0;
1319 }
1320
1321 void
1322 pb_obj::set_hdmv(int id, int pt)
1323 {
1324   obj_typ = obj_hdmv;
1325   pb_typ = pt;
1326   delete [] bdj_name;
1327   bdj_name = 0;
1328   hdmv_id = id;
1329 }
1330
1331 void
1332 pb_obj::set_bdj(char *nm, int pt)
1333 {
1334   obj_typ = obj_bdj;
1335   pb_typ = pt;
1336   delete [] bdj_name;
1337   bdj_name = 0;
1338   bdj_name = cstrdup(nm);
1339 }
1340
1341 void 
1342 pb_obj::write_hdmv_obj(int id_ref)
1343 {
1344   bs.write(pb_typ, 2);
1345   bs.write(0, 14);
1346   bs.write(id_ref, 16);
1347   bs.write(0, 32);
1348 }
1349
1350 void
1351 pb_obj::write_bdj_obj(char *name)
1352 {
1353   bs.write(pb_typ, 2);
1354   bs.write(0, 14);
1355   bs.writeb(name, 5);
1356   bs.write(0, 8);
1357 }
1358
1359 void
1360 pb_obj::write_obj()
1361 {
1362   switch (obj_typ) {
1363   case obj_bdj:
1364     write_bdj_obj(bdj_name);
1365     break;
1366   case obj_hdmv:
1367   default:
1368     write_hdmv_obj(hdmv_id);
1369     break;
1370   }
1371 }
1372
1373 void
1374 title_obj::write_obj()
1375 {
1376   bs.write(obj_typ, 2);
1377   bs.write(acc_typ, 2);
1378   bs.write(0, 28);
1379   pb_obj::write_obj();
1380 }
1381
1382
1383 void
1384 index_file::write_pb_obj(pb_obj * pb)
1385 {
1386   bs.write(pb->obj_typ, 2);
1387   bs.write(0, 30);
1388   pb->write_obj();
1389 }
1390
1391 int
1392 index_file::write()
1393 {
1394   // output header
1395   bs.writeb("INDX", 4);
1396   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1397   bs_ofs(bs, 32);
1398   exten.bs_ofs(bs, 32);
1399   int appinfo_start = 0x28;
1400   bs.posb(appinfo_start);
1401   appinf.bs_len(bs, 32);
1402   bs.write(1, 1);
1403   bs.write(initial_output_mode_preference, 1);
1404   bs.write(content_exist_flag, 1);
1405   bs.write(0, 5);
1406   bs.write(video_format, 4);
1407   bs.write(frame_rate, 4);
1408   bs.writeb(user_data, 32);
1409   appinf.bs_end(bs);
1410
1411   // output index
1412   bs_len(bs, 32);
1413   write_pb_obj(&first_play);
1414   write_pb_obj(&top_menu);
1415   bs.write(titles.size(), 16);
1416
1417   for (int i = 0; i < titles.size(); ++i)
1418     titles[i]->write_obj();
1419   bs_end(bs);
1420   exten.bs_len(bs,32);
1421   exten.bs_end(bs);
1422   return 0;
1423 }
1424
1425
1426
1427 int
1428 bdid::write()
1429 {
1430   bs.writeb("BDID",4);
1431   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1432   bs.write(data_start, 32);
1433   bs.write(extension_data_start, 32);
1434   bs.posb(40 - 16);
1435   bs.writeb(org_id, sizeof(org_id));
1436   bs.writeb(disc_id, sizeof(disc_id));
1437   return 0;
1438 }
1439
1440 // XXX - not current referenced
1441 #if 0
1442 int
1443 bdmv_write_extension_data(int start_address,
1444         int (*handler) (int, int, void *), void *handle)
1445 {
1446   int64_t length;
1447   int num_entries, n;
1448
1449   bs.write(length, 32);   /* length of extension data block */
1450   if( length < 1 )
1451     return 1;
1452
1453   bs.pad(32);             /* relative start address of extension data */
1454   bs.pad(24);             /* padding */
1455   bs.write(num_entries, 8);
1456
1457   for (n = 0; n < num_entries; n++) {
1458     bs.write(id1, 16);
1459     bs.write(id2, 16);
1460     bs.write(ext_start, 32);
1461     bs.write(ext_len, 32);
1462     saved_pos = bs.pos() >> 3;
1463     bs.posb(start_address + ext_start);
1464     handler(id1, id2, handle);
1465     bs.posb(saved_pos);
1466   }
1467
1468   return 0;
1469 }
1470 #endif
1471
1472 int
1473 clpi_prog_stream::write()
1474 {
1475   bs.write(pid, 16);
1476   bs_len(bs, 8);
1477
1478   bs.write(coding_type, 8);
1479   switch (coding_type) {
1480   case BLURAY_STREAM_TYPE_VIDEO_MPEG1:
1481   case BLURAY_STREAM_TYPE_VIDEO_MPEG2:
1482   case BLURAY_STREAM_TYPE_VIDEO_VC1:
1483   case BLURAY_STREAM_TYPE_VIDEO_H264:
1484   case 0x20:
1485     bs.write(format, 4);
1486     bs.write(rate, 4);
1487     bs.write(aspect, 4);
1488     bs.pad(2);
1489     bs.write(oc_flag, 1);
1490     bs.pad(1);
1491     break;
1492
1493   case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
1494   case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
1495   case BLURAY_STREAM_TYPE_AUDIO_LPCM:
1496   case BLURAY_STREAM_TYPE_AUDIO_AC3:
1497   case BLURAY_STREAM_TYPE_AUDIO_DTS:
1498   case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
1499   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
1500   case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
1501   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
1502   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS_SECONDARY:
1503   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_SECONDARY:
1504     bs.write(format, 4);
1505     bs.write(rate, 4);
1506     bs.writeb(lang, 3);
1507     break;
1508
1509   case BLURAY_STREAM_TYPE_SUB_PG:
1510   case BLURAY_STREAM_TYPE_SUB_IG:
1511   case 0xa0:
1512     bs.writeb(lang, 3);
1513     break;
1514
1515   case BLURAY_STREAM_TYPE_SUB_TEXT:
1516     bs.write(char_code, 8);
1517     bs.writeb(lang, 3);
1518     break;
1519
1520   default:
1521     fprintf(stderr, "clpi_prog_stream: unrecognized coding type %02x\n",
1522             coding_type);
1523     return 1;
1524   };
1525
1526   bs_end(bs);
1527   return 0;
1528 }
1529
1530 int
1531 clpi_cl::write_header()
1532 {
1533   bs.writeb("HDMV", 4);
1534   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1535   bs.write(sequence_info_start_addr, 32);
1536   bs.write(program_info_start_addr, 32);
1537   bs.write(cpi_start_addr, 32);
1538   bs.write(clip_mark_start_addr, 32);
1539   bs.write(ext_data_start_addr, 32);
1540   return 0;
1541 }
1542
1543 int
1544 clpi_atc_delta::write()
1545 {
1546   bs.write(delta, 32);
1547   bs.writeb(file_id, 5);
1548   bs.writeb(file_code, 4);
1549   bs.pad(8);
1550   return 0;
1551 }
1552
1553 int
1554 clpi_clip_info::write()
1555 {
1556   bs.posb(40);
1557   bs_len(bs, 32);
1558
1559   bs.pad(16);                   // reserved
1560   bs.write(clip_stream_type, 8);
1561   bs.write(application_type, 8);
1562   bs.pad(31);                   // skip reserved 31 bits
1563   bs.write(is_atc_delta, 1);
1564   bs.write(ts_recording_rate, 32);
1565   bs.write(num_source_packets, 32);
1566
1567   bs.padb(128);                 // Skip reserved 128 bytes
1568
1569   // ts type info block
1570   int ts_len = 30;
1571   bs.write(ts_len, 16);
1572   int64_t pos = bs.posb();
1573   if( ts_len ) {
1574     bs.write(ts_type_info.validity, 8);
1575     bs.writeb(ts_type_info.format_id, 4);
1576     // pad the stuff we don't know anything about
1577     bs.padb(ts_len - (bs.posb() - pos));
1578   }
1579
1580   if( is_atc_delta ) {
1581     bs.pad(8);                  // Skip reserved byte
1582     bs.write(atc_delta.size(), 8);
1583     for( int ii=0; ii < atc_delta.size(); ++ii )
1584       if( atc_delta[ii]->write() ) return 1;
1585   }
1586
1587   // font info
1588   if( application_type == 6 /* Sub TS for a sub-path of Text subtitle */  ) {
1589     bs.pad(8);
1590     bs.write(font_info.font.size(), 8);
1591     if( font_info.font.size() ) {
1592       for( int ii=0; ii < font_info.font.size(); ++ii ) {
1593         bs.writeb(font_info.font[ii]->file_id, 5);
1594         bs.pad(8);
1595       }
1596     }
1597   }
1598
1599   bs_end(bs);
1600   return 0;
1601 }
1602
1603 int
1604 clpi_stc_seq::write()
1605 {
1606   bs.write(pcr_pid, 16);
1607   bs.write(spn_stc_start, 32);
1608   bs.write(presentation_start_time, 32);
1609   bs.write(presentation_end_time, 32);
1610   return 0;
1611 }
1612
1613 int
1614 clpi_atc_seq::write()
1615 {
1616   bs.write(spn_atc_start, 32);
1617   bs.write(stc_seq.size(), 8);
1618   bs.write(offset_stc_id, 8);
1619
1620   for( int ii=0; ii < stc_seq.size(); ++ii )
1621     if( stc_seq[ii]->write() ) return 1;
1622   return 0;
1623 }
1624
1625 int
1626 clpi_sequences::write()
1627 {
1628   bs_len(bs, 32);
1629   bs.padb(1);                   // reserved byte
1630   bs.write(size(), 8);
1631   for( int ii=0; ii < size(); ++ii )
1632     if( get(ii)->write() ) return 1;
1633   bs_end(bs);
1634   return 0;
1635 }
1636
1637 int
1638 clpi_prog::write()
1639 {
1640   bs.write(spn_program_sequence_start, 32);
1641   bs.write(program_map_pid, 16);
1642   bs.write(streams.size(), 8);
1643   bs.write(num_groups, 8);
1644   for( int ii=0; ii < streams.size(); ++ii )
1645     if( streams[ii]->write() ) return 1;
1646   return 0;
1647 }
1648
1649 int
1650 clpi_programs::write()
1651 {
1652   bs_len(bs, 32);
1653   bs.padb(1);                   // reserved byte
1654   bs.write(size(), 8);
1655   for( int ii=0; ii < size(); ++ii )
1656     if( get(ii)->write() ) return 1;
1657   bs_end(bs);
1658   return 0;
1659 }
1660
1661 int
1662 clpi_ep_coarse::write()
1663 {
1664   bs.write(ref_ep_fine_id, 18);
1665   bs.write(pts_ep, 14);
1666   bs.write(spn_ep, 32);
1667   return 0;
1668 }
1669
1670 int
1671 clpi_ep_fine::write()
1672 {
1673   bs.write(is_angle_change_point, 1);
1674   bs.write(i_end_position_offset, 3);
1675   bs.write(pts_ep, 11);
1676   bs.write(spn_ep, 17);
1677   return 0;
1678 }
1679
1680 int
1681 clpi_ep_map_entry::write(uint32_t ep_map_pos)
1682 {
1683   bs.write(pid, 16);
1684   bs.pad(10);
1685   bs.write(ep_stream_type, 4);
1686   bs.write(coarse.size(), 16);
1687   bs.write(fine.size(), 18);
1688   bs.write(ep_map_stream_start_addr - ep_map_pos, 32);
1689   return 0;
1690 }
1691
1692 int
1693 clpi_ep_map_entry::write_map()
1694 {
1695   ep_map_stream_start_addr = bs.posb();
1696   bs.write(fine_start, 32);
1697
1698   for( int ii=0; ii < coarse.size(); ++ii )
1699     if( coarse[ii]->write() ) return 1;
1700
1701   fine_start = bs.posb() - ep_map_stream_start_addr;
1702   for( int ii=0; ii < fine.size(); ++ii )
1703     if( fine[ii]->write() ) return 1;
1704
1705   return 0;
1706 }
1707
1708 int
1709 clpi_cpi::write()
1710 {
1711   bs_len(bs, 32);
1712   bs.pad(12);
1713   bs.write(type, 4);
1714   uint32_t ep_map_pos = bs.posb();
1715
1716   // EP Map starts here
1717   bs.pad(8);
1718   bs.write(size(), 8);
1719
1720   for( int ii=0; ii < size(); ++ii )
1721     if( get(ii)->write(ep_map_pos) ) return 1;
1722
1723   for( int ii=0; ii < size(); ++ii )
1724     if( get(ii)->write_map() ) return 1;
1725
1726   bs_end(bs);
1727   return 0;
1728 }
1729
1730 int
1731 clpi_extents::write()
1732 {
1733   bs_len(bs, 32);
1734   bs.write(size(), 32);
1735   for( int ii=0; ii < size(); ++ii )
1736     bs.write(get(ii), 32);
1737   return 0;
1738 }
1739
1740 int
1741 clpi_cl::write_clpi_extension(int id1, int id2, void *handle)
1742 {
1743   clpi_cl *cl = (clpi_cl *) handle;
1744
1745   if( id1 == 1 ) {
1746     if( id2 == 2 ) {
1747       // LPCM down mix coefficient
1748       //write_lpcm_down_mix_coeff(&cl->lpcm_down_mix_coeff);
1749       return 0;
1750     }
1751   }
1752
1753   if( id1 == 2 ) {
1754     if( id2 == 4 ) {
1755       // Extent start point
1756       return cl->extents.write();
1757     }
1758     if( id2 == 5 ) {
1759       // ProgramInfo SS
1760       return cl->programs_ss.write();
1761     }
1762     if( id2 == 6 ) {
1763       // CPI SS
1764       return cl->cpi_ss.write();
1765     }
1766   }
1767
1768   fprintf(stderr, "write_clpi_extension(): unhandled extension %d.%d\n", id1, id2);
1769   return 1;
1770 }
1771
1772 int
1773 clpi_cl::write()
1774 {
1775   if( write_header() ) return 1;
1776   if( clip.write() ) return 1;
1777   sequence_info_start_addr = bs.posb();
1778   if( sequences.write() ) return 1;
1779   program_info_start_addr = bs.posb();
1780   if( programs.write() ) return 1;
1781   cpi_start_addr = bs.posb();
1782   if( cpi.write() ) return 1;
1783 //if( has_ext_data ) {
1784 //  ext_data_start_addr = bs.pos();
1785 //  bdmv_write_extension_data(write_clpi_extension, this);
1786 //}
1787   return 0;
1788 }
1789
1790 int
1791 bd_uo_mask::write()
1792 {
1793   bs.write(menu_call, 1);
1794   bs.write(title_search, 1);
1795   bs.write(chapter_search, 1);
1796   bs.write(time_search, 1);
1797   bs.write(skip_to_next_point, 1);
1798   bs.write(skip_to_prev_point, 1);
1799   bs.write(play_firstplay, 1);
1800   bs.write(stop, 1);
1801   bs.write(pause_on, 1);
1802   bs.write(pause_off, 1);
1803   bs.write(still_off, 1);
1804   bs.write(forward, 1);
1805   bs.write(backward, 1);
1806   bs.write(resume, 1);
1807   bs.write(move_up, 1);
1808   bs.write(move_down, 1);
1809   bs.write(move_left, 1);
1810   bs.write(move_right, 1);
1811   bs.write(select, 1);
1812   bs.write(activate, 1);
1813   bs.write(select_and_activate, 1);
1814   bs.write(primary_audio_change, 1);
1815   bs.pad(1);
1816   bs.write(angle_change, 1);
1817   bs.write(popup_on, 1);
1818   bs.write(popup_off, 1);
1819   bs.write(pg_enable_disable, 1);
1820   bs.write(pg_change, 1);
1821   bs.write(secondary_video_enable_disable, 1);
1822   bs.write(secondary_video_change, 1);
1823   bs.write(secondary_audio_enable_disable, 1);
1824   bs.write(secondary_audio_change, 1);
1825   bs.pad(1);
1826   bs.write(pip_pg_change, 1);
1827   bs.pad(30);
1828   return 0;
1829 }
1830
1831 int
1832 mpls_ai::write()
1833 {
1834   bs_len(bs, 32);
1835   bs.pad(8);              // Reserved
1836   bs.write(playback_type, 8);
1837   if (playback_type == BLURAY_PLAYBACK_TYPE_RANDOM ||
1838       playback_type == BLURAY_PLAYBACK_TYPE_SHUFFLE ) {
1839     bs.write(playback_count, 16);
1840   }
1841   else {
1842     bs.pad(16);           // Reserved
1843   }
1844   uo_mask.write();
1845   bs.write(random_access_flag, 1);
1846   bs.write(audio_mix_flag, 1);
1847   bs.write(lossless_bypass_flag, 1);
1848   bs.pad(13);             // Reserved
1849   bs_end(bs);
1850   return 0;
1851 }
1852
1853 int
1854 mpls_pl::write_header()
1855 {
1856   bs.writeb("MPLS", 4);
1857   bs.writeb(sig == 1 ? "0100" : "0200", 4);
1858   bs.write(list_pos, 32);
1859   bs.write(mark_pos, 32);
1860   bs.write(ext_pos, 32);
1861   bs.pad(160);            // Skip 160 reserved bits
1862   app_info.write();
1863   return 0;
1864 }
1865
1866 int mpls_stream::
1867 write()
1868 {
1869   strm.bs_len(bs, 8);
1870
1871   bs.write(stream_type, 8);
1872   switch (stream_type) {
1873   case 0x01:
1874     bs.write(pid, 16);
1875     break;
1876
1877   case 0x02:
1878   case 0x04:
1879     bs.write(subpath_id, 8);
1880     bs.write(subclip_id, 8);
1881     bs.write(pid, 16);
1882     break;
1883
1884   case 0x03:
1885     bs.write(subpath_id, 8);
1886     bs.write(pid, 16);
1887     break;
1888
1889   default:
1890     fprintf(stderr, "unrecognized stream type %02x\n", stream_type);
1891     break;
1892   };
1893   strm.bs_end(bs);
1894
1895   code.bs_len(bs, 8);
1896   bs.write(coding_type, 8);
1897   switch (coding_type) {
1898   case BLURAY_STREAM_TYPE_VIDEO_MPEG1:
1899   case BLURAY_STREAM_TYPE_VIDEO_MPEG2:
1900   case BLURAY_STREAM_TYPE_VIDEO_VC1:
1901   case BLURAY_STREAM_TYPE_VIDEO_H264:
1902     bs.write(format, 4);
1903     bs.write(rate, 4);
1904     break;
1905
1906   case BLURAY_STREAM_TYPE_AUDIO_MPEG1:
1907   case BLURAY_STREAM_TYPE_AUDIO_MPEG2:
1908   case BLURAY_STREAM_TYPE_AUDIO_LPCM:
1909   case BLURAY_STREAM_TYPE_AUDIO_AC3:
1910   case BLURAY_STREAM_TYPE_AUDIO_DTS:
1911   case BLURAY_STREAM_TYPE_AUDIO_TRUHD:
1912   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS:
1913   case BLURAY_STREAM_TYPE_AUDIO_DTSHD:
1914   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER:
1915   case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS_SECONDARY:
1916   case BLURAY_STREAM_TYPE_AUDIO_DTSHD_SECONDARY:
1917     bs.write(format, 4);
1918     bs.write(rate, 4);
1919     bs.writeb(lang, 3);
1920     break;
1921
1922   case BLURAY_STREAM_TYPE_SUB_PG:
1923   case BLURAY_STREAM_TYPE_SUB_IG:
1924     bs.writeb(lang, 3);
1925     break;
1926
1927   case BLURAY_STREAM_TYPE_SUB_TEXT:
1928     bs.write(char_code, 8);
1929     bs.writeb(lang, 3);
1930     break;
1931
1932   default:
1933     fprintf(stderr, "mpls_stream: unrecognized coding type %02x\n", coding_type);
1934     break;
1935   };
1936   code.bs_end(bs);
1937   return 0;
1938 }
1939
1940 int
1941 mpls_stn::write()
1942 {
1943   bs_len(bs, 16);
1944   bs.pad(16);             // Skip 2 reserved bytes
1945
1946   bs.write(video.size(), 8);
1947   bs.write(audio.size(), 8);
1948   bs.write(pg.size() - num_pip_pg, 8);
1949   bs.write(ig.size(), 8);
1950   bs.write(secondary_audio.size(), 8);
1951   bs.write(secondary_video.size(), 8);
1952   bs.write(num_pip_pg, 8);
1953
1954   // 5 reserve bytes
1955   bs.pad(5 * 8);
1956
1957   // Primary Video Streams
1958   for( int ii=0; ii < video.size(); ++ii )
1959     if( video[ii]->write() ) return 1;
1960
1961   // Primary Audio Streams
1962   for( int ii=0; ii < audio.size(); ++ii )
1963     if( audio[ii]->write() ) return 1;
1964
1965   // Presentation Graphic Streams
1966   for( int ii=0; ii < pg.size(); ++ii )
1967     if( pg[ii]->write() ) return 1;
1968
1969   // Interactive Graphic Streams
1970   for( int ii=0; ii < ig.size(); ++ii )
1971     if( ig[ii]->write() ) return 1;
1972
1973   // Secondary Audio Streams
1974   for( int ii=0; ii < secondary_audio.size(); ++ii ) {
1975     if( secondary_audio[ii]->write() ) return 1;
1976     // Read Secondary Audio Extra Attributes
1977     bs.write(sa_primary_audio_ref.size(), 8);
1978     bs.pad(8);
1979     for( int jj=0; jj < sa_primary_audio_ref.size(); ++jj )
1980       bs.write(sa_primary_audio_ref[jj], 8);
1981     if( sa_primary_audio_ref.size() % 2) bs.pad(8 );
1982   }
1983
1984   // Secondary Video Streams
1985   for( int ii=0; ii < secondary_video.size(); ++ii ) {
1986     if( secondary_video[ii]->write() ) return 1;
1987     // Read Secondary Video Extra Attributes
1988     bs.write(sv_secondary_audio_ref.size(), 8);
1989     bs.pad(8);
1990     for( int jj=0; jj < sv_secondary_audio_ref.size(); ++jj )
1991       bs.write(sv_secondary_audio_ref[jj], 8);
1992     if( sv_secondary_audio_ref.size() % 2) bs.pad(8 );
1993     bs.write(sv_pip_pg_ref.size(), 8);
1994     bs.pad(8);
1995     for( int jj=0; jj < sv_pip_pg_ref.size(); ++jj )
1996       bs.write(sv_pip_pg_ref[jj], 8);
1997     if( sv_pip_pg_ref.size() % 2) bs.pad(8 );
1998   }
1999
2000   bs_end(bs);
2001   return 0;
2002 }
2003
2004 int
2005 mpls_pi::write()
2006 {
2007   bs_len(bs, 16);
2008   // Primary Clip identifer
2009   bs.writeb(clip[0]->clip_id, 5);
2010   bs.writeb(clip[0]->codec_id, 4); // "M2TS"
2011   bs.pad(11); // Skip reserved 11 bits
2012
2013   bs.write(is_multi_angle, 1);
2014   bs.write(connection_condition, 4);  // 0x01, 0x05, 0x06
2015
2016   bs.write(clip[0]->stc_id, 8);
2017   bs.write(in_time, 32);
2018   bs.write(out_time, 32);
2019
2020   uo_mask.write();
2021   bs.write(random_access_flag, 1);
2022   bs.pad(7);
2023   bs.write(still_mode, 8);
2024   if( still_mode == 0x01 ) {
2025     bs.write(still_time, 16);
2026   }
2027   else {
2028     bs.pad(16);
2029   }
2030
2031   if( is_multi_angle ) {
2032     bs.write(clip.size(), 8);
2033     bs.pad(6);
2034     bs.write(is_different_audio, 1);
2035     bs.write(is_seamless_angle, 1);
2036   }
2037
2038   for( int ii=1; ii < clip.size(); ++ii ) {
2039     bs.writeb(clip[ii]->clip_id, 5);
2040     bs.writeb(clip[ii]->codec_id, 4); // "M2TS"
2041     bs.write(clip[ii]->stc_id, 8);
2042   }
2043
2044   if( stn.write() ) return 1;
2045
2046   bs_end(bs);
2047   return 0;
2048 }
2049
2050 int
2051 mpls_sub_pi::write()
2052 {
2053   bs_len(bs, 16);
2054   // Primary Clip identifer
2055   bs.writeb(clip[0]->clip_id, 5);
2056   bs.writeb(clip[0]->codec_id, 4); // "M2TS"
2057   bs.pad(27);
2058
2059   bs.write(connection_condition, 4); // 0x01, 0x05, 0x06
2060
2061   bs.write(is_multi_clip, 1);
2062   bs.write(clip[0]->stc_id, 8);
2063   bs.write(in_time, 32);
2064   bs.write(out_time, 32);
2065   bs.write(sync_play_item_id, 16);
2066   bs.write(sync_pts, 32);
2067
2068   if( is_multi_clip )
2069     bs.write(clip.size(), 8);
2070
2071   for( int ii=1; ii < clip.size(); ++ii ) {
2072     // Primary Clip identifer
2073     bs.writeb(clip[ii]->clip_id, 5);
2074     bs.writeb(clip[ii]->codec_id, 4); // "M2TS"
2075     bs.write(clip[ii]->stc_id, 8);
2076   }
2077
2078   bs_end(bs);
2079   return 0;
2080 }
2081
2082 int
2083 mpls_sub::write()
2084 {
2085   bs_len(bs, 32);
2086   bs.pad(8);
2087   bs.write(type, 8);
2088   bs.pad(15);
2089   bs.write(is_repeat, 1);
2090   bs.pad(8);
2091   bs.write(sub_play_item.size(), 8);
2092
2093   for( int ii=0; ii < sub_play_item.size(); ++ii )
2094     if( sub_play_item[ii]->write() ) return 1;
2095
2096   bs_end(bs);
2097   return 0;
2098 }
2099
2100 int
2101 mpls_plm::write()
2102 {
2103   bs.write(mark_id, 8);
2104   bs.write(mark_type, 8);
2105   bs.write(play_item_ref, 16);
2106   bs.write(time, 32);
2107   bs.write(entry_es_pid, 16);
2108   bs.write(duration, 32);
2109   return 0;
2110 }
2111
2112 int
2113 mpls_pl::write_playlistmark()
2114 {
2115   mark.bs_len(bs, 32);
2116   // Then get the number of marks
2117   bs.write(play_mark.size(), 16);
2118
2119   for( int ii=0; ii < play_mark.size(); ++ii )
2120     if( play_mark[ii]->write() ) return 1;
2121
2122   mark.bs_end(bs);
2123   return 0;
2124 }
2125
2126 int
2127 mpls_pl::write_playlist()
2128 {
2129   play.bs_len(bs,32);
2130
2131   // Skip reserved bytes
2132   bs.pad(16);
2133
2134   bs.write(play_item.size(), 16);
2135   bs.write(sub_path.size(), 16);
2136
2137   for( int ii=0; ii < play_item.size(); ++ii )
2138     if( play_item[ii]->write() ) return 1;
2139
2140   for( int ii=0; ii < sub_path.size(); ++ii )
2141     if( sub_path[ii]->write() ) return 1;
2142
2143   play.bs_end(bs);
2144   return 0;
2145 }
2146
2147 int
2148 mpls_pip_data::write()
2149 {
2150   bs.write(time, 32);
2151   bs.write(xpos, 12);
2152   bs.write(ypos, 12);
2153   bs.write(scale_factor, 4);
2154   bs.pad(4);
2155   return 0;
2156 }
2157
2158 int
2159 mpls_pip_metadata::write(uint32_t start_address)
2160 {
2161
2162   bs.write(clip_ref, 16);
2163   bs.write(secondary_video_ref, 8);
2164   bs.pad(8);
2165   bs.write(timeline_type, 4);
2166   bs.write(luma_key_flag, 1);
2167   bs.write(trick_play_flag, 1);
2168   bs.pad(10);
2169   if( luma_key_flag ) {
2170     bs.pad(8);
2171     bs.write(upper_limit_luma_key, 8);
2172   }
2173   else {
2174     bs.pad(16);
2175   }
2176   bs.pad(16);
2177
2178   uint32_t data_address = 0;  // XXX
2179   bs.write(data_address, 32);
2180
2181   int64_t pos = bs.pos() / 8;
2182   bs.posb(start_address + data_address);
2183
2184   bs.write(data.size(), 16);
2185   if( data.size() < 1 ) return 1;
2186
2187   for( int ii=0; ii < data.size(); ++ii )
2188     if( data[ii]->write() ) return 1;
2189
2190   bs.posb(pos);
2191   return 0;
2192 }
2193
2194 int
2195 mpls_pl::write_pip_metadata_extension()
2196 {
2197   uint32_t pos = bs.posb();
2198   pipm.bs_len(bs, 32);
2199
2200   bs.write(ext_pip_data.size(), 16);
2201   for( int ii=0; ii < ext_pip_data.size(); ++ii )
2202     if( ext_pip_data[ii]->write(pos) ) return 1;
2203
2204   pipm.bs_end(bs);
2205   return 0;
2206 }
2207
2208 int
2209 mpls_pl::write_subpath_extension()
2210 {
2211   subx.bs_len(bs, 32);
2212
2213   bs.write(ext_sub_path.size(), 16);
2214   for( int ii=0; ii < ext_sub_path.size(); ++ii )
2215     if( ext_sub_path[ii]->write() ) return 1;
2216
2217   subx.bs_end(bs);
2218   return 0;
2219 }
2220
2221 int
2222 clpi_cl::write_mpls_extension(int id1, int id2, void *handle)
2223 {
2224   mpls_pl *pl = (mpls_pl *) handle;
2225
2226   if( id1 == 1 ) {
2227     if( id2 == 1 ) {
2228       // PiP metadata extension
2229       return pl->write_pip_metadata_extension();
2230     }
2231   }
2232
2233   if( id1 == 2 ) {
2234     if( id2 == 1 ) {
2235       return 0;
2236     }
2237     if( id2 == 2 ) {
2238       // SubPath entries extension
2239       return pl->write_subpath_extension();
2240     }
2241   }
2242
2243   return 0;
2244 }
2245
2246 int mpls_pl::
2247 write()
2248 {
2249   int ret = write_header();
2250   list_pos = bs.posb();;
2251   if( !ret ) ret = write_playlist();
2252   mark_pos = bs.posb();
2253   if( !ret ) ret = write_playlistmark();
2254 //if( has_pls_extension ) {
2255 //  ext_pos = bs.posb();
2256 //  bdmv_write_extension_data(write_mpls_extension, pl);
2257   return ret;
2258 }
2259
2260 static int
2261 mk_dir(char *path)
2262 {
2263   if( !mkdir(path, 0777) )
2264     return 0;
2265   perror(path);
2266   return 1;
2267 }
2268
2269 static int
2270 mk_bdmv_dir(char *bdmv_path)
2271 {
2272   if( mk_dir(bdmv_path) )
2273     return 1;
2274   char bdjo_path[BCTEXTLEN];
2275   sprintf(bdjo_path, "%s/BDJO", bdmv_path);
2276   if( mk_dir(bdjo_path) )
2277     return 1;
2278   char clipinf_path[BCTEXTLEN];
2279   sprintf(clipinf_path, "%s/CLIPINF", bdmv_path);
2280   if( mk_dir(clipinf_path) )
2281     return 1;
2282   char jar_path[BCTEXTLEN];
2283   sprintf(jar_path, "%s/JAR", bdmv_path);
2284   if( mk_dir(jar_path) )
2285     return 1;
2286   char playlist_path[BCTEXTLEN];
2287   sprintf(playlist_path, "%s/PLAYLIST", bdmv_path);
2288   if( mk_dir(playlist_path) )
2289     return 1;
2290   return 0;
2291 }
2292
2293 static int
2294 mkbdmv(char *path)
2295 {
2296   char bdmv_path[BCTEXTLEN];
2297   sprintf(bdmv_path, "%s/BDMV", path);
2298   if( mk_bdmv_dir(bdmv_path) ) return 1;
2299   char stream_path[BCTEXTLEN];
2300   sprintf(stream_path, "%s/BDMV/STREAM", path);
2301   if( mk_dir(stream_path) ) return 1;
2302   char auxdata_path[BCTEXTLEN];
2303   sprintf(auxdata_path, "%s/BDMV/AUXDATA", path);
2304   if( mk_dir(auxdata_path) ) return 1;
2305   char meta_path[BCTEXTLEN];
2306   sprintf(meta_path, "%s/BDMV/META", path);
2307   if( mk_dir(meta_path) ) return 1;
2308   char backup_path[BCTEXTLEN];
2309   sprintf(backup_path, "%s/BACKUP", bdmv_path);
2310   if( mk_bdmv_dir(backup_path) ) return 1;
2311   return 0;
2312 }
2313
2314 int program::
2315 build_toc(clpi_ep_map_entry *map)
2316 {
2317   clpi_ep_coarse *cp = 0;
2318   marks.sort(mark::cmpr);
2319   uint16_t ep_pid = map->pid;
2320   int64_t last_pts = -1, last_pkt = -1;
2321   for( int ii=0; ii<marks.size(); ++ii ) {
2322     mark *mp = marks[ii];
2323     if( mp->pid != ep_pid ) continue;
2324     int64_t pts = mp->pts;
2325     if( last_pts >= pts ) continue;
2326     last_pts = pts;
2327     uint32_t pkt = mp->pos / BLURAY_TS_PKTSZ;
2328     if( last_pkt >= pkt ) continue;
2329     last_pkt = pkt;
2330     int64_t coarse_pts = (pts >> 18) & ~0x01;
2331     int64_t fine_pts = (pts & 0x7ffff) >> 8;
2332     uint32_t mpkt = pkt & ~0x1ffff;
2333     if( !cp || cp->pts_ep != coarse_pts || cp->spn_ep != mpkt ) {
2334       cp = new clpi_ep_coarse();
2335       map->coarse.append(cp);
2336       cp->ref_ep_fine_id = map->fine.size();
2337       cp->pts_ep = coarse_pts;
2338       cp->spn_ep = mpkt;
2339     }
2340     clpi_ep_fine *fp = new clpi_ep_fine();
2341     map->fine.append(fp);
2342     fp->is_angle_change_point = 0;
2343 // XXX - dont know what this is
2344     fp->i_end_position_offset = 1;
2345     fp->pts_ep = fine_pts;
2346     fp->spn_ep = pkt & 0x1ffff;
2347   }
2348   return 0;
2349 }
2350
2351 const AVRational media_info::clk45k = { 1, 45000 };
2352
2353 static int bd_stream_type(AVCodecID codec_id)
2354 {
2355   int stream_type = 0;
2356   switch (codec_id) {
2357   case AV_CODEC_ID_MPEG1VIDEO:
2358   case AV_CODEC_ID_MPEG2VIDEO:
2359     stream_type = BLURAY_STREAM_TYPE_VIDEO_MPEG2;
2360     break;
2361   case AV_CODEC_ID_H264:
2362     stream_type = BLURAY_STREAM_TYPE_VIDEO_H264;
2363     break;
2364   case AV_CODEC_ID_MP2:
2365   case AV_CODEC_ID_MP3:
2366     stream_type = BLURAY_STREAM_TYPE_AUDIO_MPEG1;
2367     break;
2368   case AV_CODEC_ID_AC3:
2369     stream_type = BLURAY_STREAM_TYPE_AUDIO_AC3;
2370     break;
2371   case AV_CODEC_ID_DTS:
2372     stream_type = BLURAY_STREAM_TYPE_AUDIO_DTS;
2373     break;
2374   case AV_CODEC_ID_TRUEHD:
2375     stream_type = BLURAY_STREAM_TYPE_AUDIO_TRUHD;
2376     break;
2377   default:
2378     fprintf(stderr, "unknown bluray stream type %s\n", avcodec_get_name(codec_id));
2379     exit(1);
2380   }
2381   return stream_type;
2382 }
2383
2384 static int bd_audio_format(int channels)
2385 {
2386   int audio_format = 0;
2387   switch( channels ) {
2388   case 1:
2389     audio_format = BLURAY_AUDIO_FORMAT_MONO;
2390     break;
2391   case 2:
2392     audio_format = BLURAY_AUDIO_FORMAT_STEREO;
2393     break;
2394   case 6:
2395     audio_format = BLURAY_AUDIO_FORMAT_MULTI_CHAN;
2396     break;
2397   default:
2398     fprintf(stderr, "unknown bluray audio format %d ch\n", channels);
2399     exit(1);
2400   }
2401   return audio_format;
2402 }
2403
2404 static int bd_audio_rate(int rate)
2405 {
2406   int audio_rate = 0;
2407   switch( rate ) {
2408   case 48000:  audio_rate = BLURAY_AUDIO_RATE_48;  break;
2409   case 96000:  audio_rate = BLURAY_AUDIO_RATE_96;  break;
2410   case 192000: audio_rate = BLURAY_AUDIO_RATE_192; break;
2411   default:
2412     fprintf(stderr, "unknown bluray audio rate %d\n", rate);
2413     exit(1);
2414   }
2415   return audio_rate;
2416 }
2417
2418 static int bd_video_format(int w, int h, int ilace)
2419 {
2420   if( w == 720 && h == 480 && ilace ) return BLURAY_VIDEO_FORMAT_480I;
2421   if( w == 720 && h == 576 && ilace ) return BLURAY_VIDEO_FORMAT_576I;
2422   if( w == 720 && h == 480 && !ilace ) return BLURAY_VIDEO_FORMAT_480P;
2423   if( w == 1920 && h == 1080 && ilace ) return BLURAY_VIDEO_FORMAT_1080I;
2424   if( w == 1280 && h == 720 && !ilace ) return BLURAY_VIDEO_FORMAT_720P;
2425   if( w == 1920 && h == 1080 && !ilace ) return BLURAY_VIDEO_FORMAT_1080P;
2426   if( w == 720 && h == 576 && !ilace ) return BLURAY_VIDEO_FORMAT_576P;
2427   fprintf(stderr, "unknown bluray video format %dx%d %silace\n",
2428     w, h, !ilace ? "not " : "");
2429   exit(1);
2430 }
2431
2432 static int bd_video_rate(double rate)
2433 {
2434   if( fabs(rate-23.976) < 0.01 ) return BLURAY_VIDEO_RATE_24000_1001;
2435   if( fabs(rate-24.000) < 0.01 ) return BLURAY_VIDEO_RATE_24;
2436   if( fabs(rate-25.000) < 0.01 ) return BLURAY_VIDEO_RATE_25;
2437   if( fabs(rate-29.970) < 0.01 ) return BLURAY_VIDEO_RATE_30000_1001;
2438   if( fabs(rate-50.000) < 0.01 ) return BLURAY_VIDEO_RATE_50;
2439   if( fabs(rate-59.940) < 0.01 ) return BLURAY_VIDEO_RATE_60000_1001;
2440   fprintf(stderr, "unknown bluray video framerate %5.2f\n",rate);
2441   exit(1);
2442 }
2443
2444 static int bd_aspect_ratio(int w, double ratio)
2445 {
2446   if( fabs(ratio-1.333) < 0.01 ) return BLURAY_ASPECT_RATIO_4_3;
2447   if( fabs(ratio-1.777) < 0.01 ) return BLURAY_ASPECT_RATIO_16_9;
2448   return w == 720 ? BLURAY_ASPECT_RATIO_4_3 : BLURAY_ASPECT_RATIO_16_9; 
2449   fprintf(stderr, "unknown bluray aspect ratio %5.3f\n",ratio);
2450   exit(1);
2451 }
2452
2453 int media_info::scan()
2454 {
2455   struct stat st;
2456   if( stat(filename, &st) ) return 1;
2457   file_size = st.st_size;
2458
2459   AVFormatContext *fmt_ctx = 0;
2460   AVDictionary *fopts = 0;
2461   av_dict_set(&fopts, "formatprobesize", "5000000", 0);
2462   av_dict_set(&fopts, "scan_all_pmts", "1", 0);
2463   av_dict_set(&fopts, "threads", "auto", 0);
2464   int ret = avformat_open_input(&fmt_ctx, filename, NULL, &fopts);
2465   av_dict_free(&fopts);
2466   if( ret < 0 ) return ret;
2467   ret = avformat_find_stream_info(fmt_ctx, NULL);
2468
2469   bit_rate = fmt_ctx->bit_rate;
2470
2471   int ep_pid = -1;
2472   for( int i=0; ret>=0 && i<(int)fmt_ctx->nb_streams; ++i ) {
2473     AVStream *st = fmt_ctx->streams[i];
2474     AVMediaType type = st->codec->codec_type;
2475     switch( type ) {
2476     case AVMEDIA_TYPE_VIDEO: break;
2477     case AVMEDIA_TYPE_AUDIO: break;
2478     default: continue;
2479     }
2480     stream *s = new stream(type, i);
2481     s->pid = st->id;
2482     AVCodecID codec_id = st->codec->codec_id;
2483     switch( type ) {
2484     case AVMEDIA_TYPE_VIDEO: {
2485       if( ep_pid < 0 ) ep_pid = st->id;
2486       s->coding_type = bd_stream_type(codec_id);
2487       s->format = bd_video_format(st->codec->width, st->codec->height,
2488                 st->codec->flags & CODEC_FLAG_INTERLACED_ME);
2489       s->rate = bd_video_rate(!st->codec->framerate.den ? 0 :
2490                 (double)st->codec->framerate.num / st->codec->framerate.den);
2491       s->aspect = bd_aspect_ratio(st->codec->width,!st->sample_aspect_ratio.den ? 0 :
2492                 (double)st->sample_aspect_ratio.num / st->sample_aspect_ratio.den);
2493       break; }
2494     case AVMEDIA_TYPE_AUDIO: {
2495       s->coding_type = bd_stream_type(codec_id);
2496       s->format = bd_audio_format(st->codec->channels);
2497       s->rate = bd_audio_rate(st->codec->sample_rate);
2498       strcpy((char*)s->lang, "und");
2499       break; }
2500     default:
2501       break;
2502     }
2503     if( bit_rate > 0 && st->duration == AV_NOPTS_VALUE &&
2504         st->time_base.num < INT64_MAX / bit_rate ) {
2505       st->duration = av_rescale(8*file_size, st->time_base.den,
2506           bit_rate * (int64_t) st->time_base.num);
2507     }
2508     s->duration = av_rescale_q(st->duration, st->time_base, clk45k);
2509     streams.append(s);
2510
2511     AVCodec *decoder = avcodec_find_decoder(codec_id);
2512     AVDictionary *copts = 0;
2513     ret = avcodec_open2(st->codec, decoder, &copts);
2514   }
2515   if( ep_pid < 0 )
2516     ep_pid = fmt_ctx->nb_streams > 0 ? fmt_ctx->streams[0]->id : 0;
2517
2518   int npgm = fmt_ctx->nb_programs;
2519   if( npgm < 1 ) {
2520     program *pgm = new program(-1, 1);
2521     pgm->ep_pid = ep_pid;
2522     pgm->pmt_pid = 0x1000;
2523     pgm->pcr_pid = 0x100;
2524     pgm->duration = 0;
2525     for( int jj=0; jj<streams.size(); ++jj ) {
2526       AVStream *st = fmt_ctx->streams[jj];
2527       AVMediaType type = st->codec->codec_type;
2528       switch( type ) {
2529       case AVMEDIA_TYPE_VIDEO:
2530       case AVMEDIA_TYPE_AUDIO:
2531         break;
2532       default:
2533         continue;
2534       }
2535       pgm->strm_idx.append(jj);
2536       if( pgm->duration < st->duration )
2537         pgm->duration = av_rescale_q(st->duration, st->time_base, clk45k);
2538     }
2539     programs.append(pgm);
2540   }
2541
2542   for( int ii=0; ii<npgm; ++ii ) {
2543     AVProgram *pgrm = fmt_ctx->programs[ii];
2544     program *pgm = new program(ii, pgrm->id);
2545     pgm->pmt_pid = pgrm->pmt_pid;
2546     pgm->pcr_pid = pgrm->pcr_pid;
2547     pgm->duration = 0;
2548     ep_pid = -1;
2549     for( int jj=0; jj<(int)pgrm->nb_stream_indexes; ++jj ) {
2550       int av_idx = pgrm->stream_index[jj];
2551       AVStream *st = fmt_ctx->streams[av_idx];
2552       AVMediaType type = st->codec->codec_type;
2553       switch( type ) {
2554       case AVMEDIA_TYPE_VIDEO:
2555         if( ep_pid < 0 ) ep_pid = st->id;
2556         break;
2557       case AVMEDIA_TYPE_AUDIO:
2558         break;
2559       default:
2560         continue;
2561       }
2562       int sidx = streams.size();
2563       while( --sidx>=0 && streams[sidx]->av_idx!=av_idx );
2564       if( sidx < 0 ) {
2565         fprintf(stderr, "bad stream idx %d in pgm %d\n",av_idx, ii);
2566         continue;
2567       }
2568       if( pgm->duration < st->duration )
2569         pgm->duration = av_rescale_q(st->duration, st->time_base, clk45k);
2570       pgm->strm_idx.append(sidx);
2571     }
2572     if( ep_pid < 0 ) {
2573       AVProgram *pgrm = fmt_ctx->programs[0];
2574       ep_pid = pgrm->nb_stream_indexes > 0 ?
2575           fmt_ctx->streams[pgrm->stream_index[0]]->id : 0;
2576     }
2577     pgm->ep_pid = ep_pid;
2578     programs.append(pgm);
2579   }
2580
2581   if( ret >= 0 )
2582     ret = scan(fmt_ctx);
2583
2584   for( int i=0; i<(int)fmt_ctx->nb_streams; ++i )
2585     avcodec_close(fmt_ctx->streams[i]->codec);
2586   avformat_close_input(&fmt_ctx);
2587
2588   return ret;
2589 }
2590
2591 int media_info::scan(AVFormatContext *fmt_ctx)
2592 {
2593   int ret = 0;
2594   AVPacket ipkt;
2595   av_init_packet(&ipkt);
2596
2597   for( int64_t count=0; ret>=0; ++count ) {
2598     av_packet_unref(&ipkt);
2599     ipkt.data = 0; ipkt.size = 0;
2600
2601     ret = av_read_frame(fmt_ctx, &ipkt);
2602     if( ret < 0 ) {
2603       if( ret == AVERROR_EOF ) break;
2604       ret = 0;
2605       continue;
2606     }
2607     if( !ipkt.data ) continue;
2608     if( (ipkt.flags & AV_PKT_FLAG_CORRUPT) ) continue;
2609     if( ipkt.pts == AV_NOPTS_VALUE ) continue;
2610     int i = ipkt.stream_index;
2611     if( i < 0 || i >= streams.size() ) continue;
2612
2613     stream *sp = 0;
2614     program *pgm = 0;
2615     for( int ii=0; !pgm && ii<programs.size(); ++ii ) {
2616       program *p = programs[ii];
2617       for( int jj=0; jj<p->strm_idx.size(); ++jj ) {
2618         sp = streams[p->strm_idx[jj]];
2619         if( sp->av_idx == i ) { pgm = p;  break; }
2620       }
2621     }
2622     if( !pgm ) continue;
2623     AVStream *st = fmt_ctx->streams[i];
2624     if( pgm->ep_pid != st->id ) continue;
2625     int64_t pts45k = av_rescale_q(ipkt.pts, st->time_base, clk45k);
2626     if( sp->start_pts > pts45k ) sp->start_pts = pts45k;
2627     if( sp->end_pts < pts45k ) sp->end_pts = pts45k;
2628     if( pgm->start_time > pts45k ) pgm->start_time = pts45k;
2629     if( pgm->end_time < pts45k ) pgm->end_time = pts45k;
2630
2631     if( !(ipkt.flags & AV_PKT_FLAG_KEY) ) continue;
2632
2633     if( sp->last_pts != pts45k ) {
2634       sp->last_pts = pts45k;
2635       pgm->add_label(count, ipkt.pos, pts45k, st->id);
2636     }
2637   }
2638
2639   for( int ii=0; ii<programs.size(); ++ii ) {
2640     program *pgm = programs[ii];
2641     if( pgm->end_time > pgm->start_time )
2642       pgm->duration = pgm->end_time - pgm->start_time;
2643   }
2644
2645   return ret != AVERROR_EOF ? -1 : 0;
2646 }
2647
2648 int
2649 Media::compose()
2650 {
2651 // index
2652   bs.init();
2653   idx.sig = 1;
2654   idx.first_play.set_hdmv(0, pb_typ_movie);
2655   idx.top_menu.set_hdmv(0xffff, pb_typ_iactv);
2656
2657 // movie
2658   bs.init();
2659   mov.sig = 1;
2660   movie_obj *mp = new movie_obj();
2661   mp->resume_intention_flag = 1;
2662   command_obj *cmd = new command_obj();
2663   cmd->cmd = htobe32(0x21810000); cmd->dst = 1; cmd->src = 0;
2664   mp->cmds.append(cmd);  // JUMP_TITLE 1
2665   cmd = new command_obj();
2666   cmd->cmd = htobe32(0x00020000); cmd->dst = 0; cmd->src = 0;
2667   mp->cmds.append(cmd);
2668   mov.movies.append(mp); // BREAK
2669
2670   
2671   for( int ii=0; ii<size(); ++ii ) {
2672     mp = new movie_obj();
2673     mp->resume_intention_flag = 1;
2674     cmd = new command_obj();
2675     cmd->cmd = htobe32(0x22800000); cmd->dst = ii; cmd->src = 0;
2676     mp->cmds.append(cmd);  // PLAY_PL   ii
2677     cmd = new command_obj();
2678     cmd->cmd = htobe32(0x00020000); cmd->dst = 0; cmd->src = 0;
2679     mp->cmds.append(cmd);
2680     mov.movies.append(mp); // BREAK
2681   }
2682
2683   mp = new movie_obj();
2684   mp->resume_intention_flag = 1;
2685   cmd = new command_obj();
2686   cmd->cmd = htobe32(0x21810000); cmd->dst = 1; cmd->src = 0;
2687   mp->cmds.append(cmd);  // JUMP_TITLE 1
2688   cmd = new command_obj();
2689   cmd->cmd = htobe32(0x00020000); cmd->dst = 0; cmd->src = 0;
2690   mp->cmds.append(cmd);
2691   mov.movies.append(mp); // BREAK
2692
2693   title_obj *tp = 0;
2694 // clips
2695   for( int ii=0; ii<size(); ++ii ) {
2696     if( !tp ) {
2697       tp = new title_obj();
2698       tp->set_hdmv(idx.titles.size()+1, pb_typ_movie);
2699       idx.titles.append(tp);
2700     }
2701     bs.init();
2702     media_info *ip = get(ii);
2703 // clip program, if specified
2704     int pidx = ip->programs.size();
2705     while( --pidx>=0 && ip->programs[pidx]->pid != ip->pgm_pid );
2706     if( pidx < 0 ) pidx = 0;
2707     ip->pidx = pidx;
2708     ip->pgm_pid = ip->prog()->pid;
2709
2710     clpi_cl *cp = new clpi_cl();
2711     cp->clip.clip_stream_type = 1;
2712     cp->clip.application_type = BLURAY_APP_TYPE_MAIN_MOVIE;
2713     cp->clip.ts_recording_rate = ip->bit_rate;
2714     uint32_t ts_pkt_count = ip->file_size / BLURAY_TS_PKTSZ + 1;
2715     cp->clip.num_source_packets = ts_pkt_count;
2716     cp->clip.ts_type_info.validity = 0x80;
2717     strcpy(cp->clip.ts_type_info.format_id, "HDMV");
2718     cp->cpi.type = 1;
2719
2720     for( int jj=0; jj<ip->programs.size(); ++jj ) {
2721       program *pgm = ip->programs[jj];
2722       clpi_prog *p = new clpi_prog(pgm->pmt_pid);
2723       for( int kk=0; kk<pgm->strm_idx.size(); ++kk ) {
2724         int k = pgm->strm_idx[kk];
2725         stream *sp = ip->streams[k];
2726         clpi_prog_stream *s = new clpi_prog_stream();
2727         s->pid = sp->pid;
2728         s->coding_type = sp->coding_type;
2729         s->format = sp->format;
2730 //use unspecified (0)
2731 //      if( !idx.video_format ) idx.video_format = s->format;
2732         s->rate = sp->rate;
2733 //      if( !idx.frame_rate ) idx.frame_rate = s->rate;
2734         switch( sp->type ) {
2735         case AVMEDIA_TYPE_VIDEO:
2736           s->aspect = sp->aspect;
2737           break;
2738         case AVMEDIA_TYPE_AUDIO:
2739           memcpy(s->lang,sp->lang,sizeof(s->lang));
2740           break;
2741         default:
2742           break;
2743         }
2744         p->streams.append(s);
2745       }
2746       clpi_ep_map_entry *map = new clpi_ep_map_entry(pgm->ep_pid);
2747       pgm->build_toc(map);
2748       cp->cpi.append(map);
2749       cp->programs.append(p);
2750
2751       clpi_atc_seq *atc_seq = new clpi_atc_seq();
2752       clpi_stc_seq *stc_seq = new clpi_stc_seq();
2753       stc_seq->pcr_pid = pgm->pcr_pid;
2754       stc_seq->presentation_start_time = pgm->start_time;
2755       stc_seq->presentation_end_time = pgm->end_time;
2756       atc_seq->stc_seq.append(stc_seq);
2757       cp->sequences.append(atc_seq);
2758     }
2759
2760     cl.append(cp);
2761     tp->last = ii;
2762     if( ip->brk ) tp = 0;
2763   }
2764
2765 // playlists, one per title
2766 //   one playitem per media clip
2767   int clip_id = 0;
2768   for( int ii=0; ii<idx.titles.size(); ++ii ) {
2769     bs.init();
2770     media_info *ip = get(clip_id);
2771     program *pgm = ip->prog();
2772     mpls_pl *pp = new mpls_pl();
2773     pp->app_info.playback_type = BLURAY_PLAYBACK_TYPE_SEQUENTIAL;
2774 //  pp->app_info.uo_mask.xxx = 1;
2775     int last = idx.titles[ii]->last;
2776     for( ; clip_id<=last; ++clip_id ) {
2777       ip = get(clip_id);
2778       pgm = ip->prog();
2779       mpls_pi *pi = new mpls_pi();
2780       pi->connection_condition = 1; // seamless
2781       pi->in_time = pgm->start_time;
2782       pi->out_time = pgm->end_time;
2783       if( ip->still )
2784         pi->still_mode = BLURAY_STILL_INFINITE;
2785       int64_t end_time = pgm->start_time + pgm->duration;
2786       if( pi->out_time < end_time ) pi->out_time = end_time;
2787       mpls_clip *cp = new mpls_clip();
2788       sprintf(cp->clip_id,"%05d", clip_id);
2789       pi->clip.append(cp);
2790       for( int kk=0; kk<ip->streams.size(); ++kk ) {
2791         stream *sp = ip->streams[kk];
2792         switch( sp->type ) {
2793         case AVMEDIA_TYPE_VIDEO: break;
2794         case AVMEDIA_TYPE_AUDIO: break;
2795         default: continue;
2796         }
2797         mpls_stream *ps = new mpls_stream();
2798         ps->pid = sp->pid;
2799         ps->stream_type = BLURAY_PG_TEXTST_STREAM;
2800         ps->coding_type = sp->coding_type;
2801         ps->format = sp->format;
2802         ps->rate = sp->rate;
2803         switch( sp->type ) {
2804         case AVMEDIA_TYPE_VIDEO:
2805           pi->stn.video.append(ps);
2806           break;
2807         case AVMEDIA_TYPE_AUDIO:
2808           memcpy(ps->lang, sp->lang, sizeof(ps->lang));
2809           pi->stn.audio.append(ps);
2810           break;
2811         default:
2812           break;
2813         }
2814       }
2815       pp->play_item.append(pi);
2816     }
2817 // chapter marks every ch_duration ticks
2818     int64_t ch_duration = 45000 * 60*10;
2819     int64_t mrktm = ch_duration;
2820     int64_t plytm = 0;
2821     int pmark = 0, pitem = 0;
2822     mpls_pi *pi = pp->play_item[pitem];
2823     mpls_plm *pm = new mpls_plm();
2824     pm->mark_id = pmark++;
2825     pm->mark_type = BLURAY_MARK_TYPE_ENTRY;
2826     pm->play_item_ref = pitem;
2827     pm->time = pi->in_time;
2828     pm->entry_es_pid = 0;
2829     pp->play_mark.append(pm);
2830     for( int jj=0; jj < pp->play_item.size(); ++jj ) {
2831       pitem = jj;
2832       pi = pp->play_item[pitem];
2833       int64_t pi_duration = pi->out_time - pi->in_time;
2834       int64_t endtm = plytm + pi_duration;
2835       while( mrktm < endtm ) {
2836         pm = new mpls_plm();
2837         pm->mark_id = pmark++;
2838         pm->mark_type = BLURAY_MARK_TYPE_ENTRY;
2839         pm->play_item_ref = pitem;
2840         pm->time = pi->in_time + mrktm - plytm;
2841         pm->entry_es_pid = 0;
2842         pp->play_mark.append(pm);
2843         mrktm += ch_duration;
2844       }
2845       plytm = endtm;
2846     }
2847     pm = new mpls_plm();
2848     pm->mark_id = pmark;
2849     pm->mark_type = BLURAY_MARK_TYPE_ENTRY;
2850     pm->play_item_ref = pitem;
2851     pm->time = pi->out_time;
2852     pm->entry_es_pid = 0;
2853     pp->play_mark.append(pm);
2854
2855     pl.append(pp);
2856   }
2857   return 0;
2858 }
2859
2860 int Media::
2861 bd_path(const char *bp, const char *fmt, va_list ap)
2862 {
2863   int n = sizeof(filename)-1;
2864   char *cp = filename;
2865   const char *pp = path;
2866   while( n>0 && (*cp=*pp)!=0 ) { --n;  ++cp;  ++pp; }
2867   while( n>0 && (*cp=*bp)!=0 ) { --n;  ++cp;  ++bp; }
2868   n -= vsnprintf(cp, n, fmt, ap);
2869   va_end(ap);
2870   return n > 0 ? 0 : 1;
2871 }
2872
2873 int Media::
2874 bd_copy(const char *ifn, const char *fmt, ...)
2875 {
2876   int n, ret = 1;
2877   char bfr[0x40000];
2878   FILE *ifp = fopen(ifn,"r");
2879   if( ifp ) {
2880     va_list ap;
2881     va_start(ap, fmt);
2882     if( bd_path("/BDMV/", fmt, ap) ) return 1;
2883     va_end(ap);
2884     FILE *ofp = fopen(filename,"w");
2885     if( ofp ) {
2886       setvbuf(ifp, 0, _IOFBF, 0x80000);
2887       setvbuf(ofp, 0, _IOFBF, 0x80000);
2888       while( (n=fread(bfr,1,sizeof(bfr),ifp)) > 0 ) fwrite(bfr,1,n,ofp);
2889       fclose(ofp);
2890       ret = 0;
2891     }
2892     fclose(ifp);
2893   }
2894   if( ret )
2895     fprintf(stderr, "cant copy clip %s\n",ifn);
2896   return ret;
2897 }
2898
2899 int Media::
2900 bd_open(const char *fmt, ...)
2901 {
2902   bs.init();
2903   if( !path ) return 0;
2904   va_list ap;
2905   va_start(ap, fmt);
2906   if( bd_path("/BDMV/", fmt, ap) ) return 1;
2907   va_end(ap);
2908   if( bs.open(filename) ) {
2909     fprintf(stderr, "cant open file %s\n",filename);
2910     return 1;
2911   }
2912   return 0;
2913 }
2914
2915 int Media::
2916 bd_backup(const char *fmt, ...)
2917 {
2918   bs.close();
2919   if( !path ) return 0;
2920   int n, ret = 1;
2921   char bfr[0x10000];
2922   FILE *ifp = fopen(filename,"r");
2923   if( ifp ) {
2924     va_list ap;
2925     va_start(ap, fmt);
2926     if( bd_path("/BDMV/BACKUP/", fmt, ap) ) return 1;
2927     va_end(ap);
2928     FILE *ofp = fopen(filename,"w");
2929     if( ofp ) {
2930       while( (n=fread(bfr,1,sizeof(bfr),ifp)) > 0 ) fwrite(bfr,1,n,ofp);
2931       fclose(ofp);
2932       ret = 0;
2933     }
2934     fclose(ifp);
2935   }
2936   if( ret )
2937     fprintf(stderr, "cant backup %s\n",filename);
2938   return ret;
2939 }
2940
2941 int Media::write(char *fn)
2942 {
2943   this->path = fn;
2944 // index
2945   if( bd_open("index.bdmv") ) return 1;
2946   if( idx.write() ) return 1;
2947   if( bd_backup("index.bdmv") ) return 1;
2948 // movie
2949   if( bd_open("MovieObject.bdmv") ) return 1;
2950   if( mov.write() ) return 1;
2951   if( bd_backup("MovieObject.bdmv") ) return 1;
2952 // clips
2953   for( int ii=0; ii<cl.size(); ++ii ) {
2954     if( bd_open("CLIPINF/%05d.clpi", ii) ) return 1;
2955     if( cl[ii]->write() ) return 1;
2956     if( bd_backup("CLIPINF/%05d.clpi", ii) ) return 1;
2957   }
2958 // playlists
2959   for( int ii=0; ii<pl.size(); ++ii ) {
2960     if( bd_open("PLAYLIST/%05d.mpls", ii) ) return 1;
2961     if( pl[ii]->write() ) return 1;
2962     if( bd_backup("PLAYLIST/%05d.mpls", ii) ) return 1;
2963   }
2964   return 0;
2965 }
2966
2967 int
2968 main(int ac, char **av)
2969 {
2970   char *path = av[1];
2971   if( mkbdmv(path) ) return 1;
2972   av_register_all();
2973   av_log_set_level(AV_LOG_FATAL);
2974   //av_log_set_level(AV_LOG_VERBOSE);
2975   //av_log_set_level(AV_LOG_DEBUG);
2976   Media media;
2977   media_info *mp = 0;
2978
2979   for( int ii=2; ii<ac; ++ii ) {
2980     char *ap = av[ii];
2981     // any dash seq followed by number sets curr title pgm_pid
2982     // single dash only sets title pgm_pid
2983     // double dash ends curr title, starts a new title
2984     // triple dash ends curr title as infinite still
2985     if( *ap == '-' ) {
2986       if( !mp ) continue;
2987       if( *++ap == '-' ) {
2988         mp->brk = 1;
2989         if( *++ap == '-' ) { ++ap;  mp->still = 1; }
2990       }
2991       if( *ap >= '0' && *ap <= '9' )
2992         mp->pgm_pid = strtoul(ap,&ap,0);
2993       if( mp->brk ) mp = 0;
2994       if( !ap || *ap ) {
2995         fprintf(stderr, "err arg %d: %s\n",ii,av[ii]);
2996         return 1;
2997       }
2998       continue;
2999     }
3000     mp = new media_info(av[ii]);
3001     media.append(mp);
3002     if( mp->scan() ) {
3003       fprintf(stderr, "cant scan media: %s\n", av[ii]);
3004       return 1;
3005     }
3006   }
3007
3008   if( mp ) mp->brk = 1;
3009
3010   if( media.compose() ) {
3011     fprintf(stderr, "cant compose media\n");
3012     return 1;
3013   }
3014   if( media.write(0) ) {
3015     fprintf(stderr, "cant prepare media\n");
3016     return 1;
3017   }
3018   if( media.write(path) ) {
3019     fprintf(stderr, "cant write media\n");
3020     return 1;
3021   }
3022
3023   for( int ii=0; ii<media.size(); ++ii )
3024     if( media.bd_copy(media[ii]->filename, "STREAM/%05d.m2ts", ii) )
3025       return 1;
3026
3027   return 0;
3028 }
3029