textbox cursor fix, h265 param files, bluray updates, new-proj theme fixes
authorGood Guy <good1.2guy@gmail.com>
Sat, 28 Jan 2017 22:11:13 +0000 (15:11 -0700)
committerGood Guy <good1.2guy@gmail.com>
Sat, 28 Jan 2017 22:11:13 +0000 (15:11 -0700)
36 files changed:
cinelerra-5.1/cinelerra/bdcreate.C
cinelerra-5.1/cinelerra/bdwrite.C
cinelerra-5.1/cinelerra/ffmpeg.C
cinelerra-5.1/cinelerra/ffmpeg.h
cinelerra-5.1/cinelerra/fileffmpeg.C
cinelerra-5.1/cinelerra/new.C
cinelerra-5.1/cinelerra/render.C
cinelerra-5.1/configure.ac
cinelerra-5.1/ffmpeg/audio/bluray.m2ts
cinelerra-5.1/ffmpeg/format/bluray [new file with mode: 0644]
cinelerra-5.1/ffmpeg/plugin.opts
cinelerra-5.1/ffmpeg/video/avc422.m2ts
cinelerra-5.1/ffmpeg/video/bluray.m2ts
cinelerra-5.1/ffmpeg/video/bluray_lo.m2ts
cinelerra-5.1/ffmpeg/video/h265-12bit.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/h265-hi.mp4 [moved from cinelerra-5.1/ffmpeg/video/h265.mp4 with 66% similarity]
cinelerra-5.1/ffmpeg/video/h265-lo.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/h265-med.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/hevc422p10.m2ts
cinelerra-5.1/ffmpeg/video/hevc422p8.m2ts
cinelerra-5.1/ffmpeg/video/lossless.m2ts
cinelerra-5.1/ffmpeg/video/visually_lossless.m2ts [new file with mode: 0644]
cinelerra-5.1/guicast/bcfilebox.C
cinelerra-5.1/guicast/bctextbox.C
cinelerra-5.1/guicast/bcwindowbase.C
cinelerra-5.1/guicast/bcwindowbase.h
cinelerra-5.1/plugins/theme_blond/data/new_bg.png
cinelerra-5.1/plugins/theme_blond_cv/data/new_bg.png
cinelerra-5.1/plugins/theme_blue/data/new_bg.png
cinelerra-5.1/plugins/theme_blue_dot/data/new_bg.png
cinelerra-5.1/plugins/theme_bright/data/new_bg.png
cinelerra-5.1/plugins/theme_hulk/data/new_bg.png
cinelerra-5.1/plugins/theme_pinklady/data/new_bg.png
cinelerra-5.1/plugins/theme_suv/data/new_bg.png
cinelerra-5.1/plugins/theme_unflat/data/new_bg.png
cinelerra-5.1/thirdparty/src/ffmpeg.patch4 [new file with mode: 0644]

index 57c207bae4e40e515e91c3757245751e7e2ceb68..b784d0ed218c7689ad5e8fca8282144219e58cfe 100644 (file)
@@ -46,10 +46,10 @@ static struct bd_format {
        { "1920x1080 24p",      1920,1080, 24.,    1, ILACE_MODE_NOTINTERLACED },
        { "1920x1080 25i",      1920,1080, 25.,    1, ILACE_MODE_TOP_FIRST },
        { "1920x1080 23.976p",  1920,1080, 23.976, 1, ILACE_MODE_NOTINTERLACED },
-       { "1440x1080 29.97i",   1440,1080, 29.97,  1, ILACE_MODE_TOP_FIRST },
-       { "1440x1080 25i",      1440,1080, 25.,    1, ILACE_MODE_TOP_FIRST },
-       { "1440x1080 24p",      1440,1080, 24.,    1, ILACE_MODE_NOTINTERLACED },
-       { "1440x1080 23.976p",  1440,1080, 23.976, 1, ILACE_MODE_NOTINTERLACED },
+       { "1440x1080 29.97i",   1440,1080, 29.97, -1, ILACE_MODE_TOP_FIRST },
+       { "1440x1080 25i",      1440,1080, 25.,   -1, ILACE_MODE_TOP_FIRST },
+       { "1440x1080 24p",      1440,1080, 24.,   -1, ILACE_MODE_NOTINTERLACED },
+       { "1440x1080 23.976p",  1440,1080, 23.976,-1, ILACE_MODE_NOTINTERLACED },
        { "1280x720  59.94p",   1280,720,  59.94,  1, ILACE_MODE_NOTINTERLACED },
        { "1280x720  50p",      1280,720,  50.,    1, ILACE_MODE_NOTINTERLACED },
        { "1280x720  24p",      1280,720,  24.,    1, ILACE_MODE_NOTINTERLACED },
@@ -69,8 +69,8 @@ const double CreateBD_Thread::BD_WIDE_ASPECT_HEIGHT = 9.;
 const double CreateBD_Thread::BD_ASPECT_WIDTH = 4.;
 const double CreateBD_Thread::BD_ASPECT_HEIGHT = 3.;
 const double CreateBD_Thread::BD_FRAMERATE = 24000. / 1001.;
-const int CreateBD_Thread::BD_MAX_BITRATE = 40000000;
-//const int CreateBD_Thread::BD_MAX_BITRATE = 8000000;
+//const int CreateBD_Thread::BD_MAX_BITRATE = 40000000;
+const int CreateBD_Thread::BD_MAX_BITRATE = 10000000;
 const int CreateBD_Thread::BD_CHANNELS = 2;
 const int CreateBD_Thread::BD_WIDE_CHANNELS = 6;
 const double CreateBD_Thread::BD_SAMPLERATE = 48000;
@@ -334,6 +334,7 @@ void CreateBD_Thread::handle_close_event(int result)
                                        edit->startproject, edit->length,
                                        PLUGIN_STANDALONE, 0, &keyframe, 0);
                        }
+                       vtrk->optimize();
                }
        }
        if( use_resize_tracks )
@@ -803,6 +804,7 @@ insert_video_plugin(const char *title, KeyFrame *default_keyframe)
                                edit->startproject, edit->length,
                                PLUGIN_STANDALONE, 0, default_keyframe, 0);
                }
+               vtrk->optimize();
        }
        return 0;
 }
@@ -838,10 +840,11 @@ option_presets()
        bd_width = bd_formats[use_standard].w;
        bd_height = bd_formats[use_standard].h;
        bd_framerate = bd_formats[use_standard].framerate;
-       bd_aspect_width = bd_formats[use_standard].wide ?
-               BD_WIDE_ASPECT_WIDTH : BD_ASPECT_WIDTH;
-       bd_aspect_height = bd_formats[use_standard].wide ?
-               BD_WIDE_ASPECT_HEIGHT : BD_ASPECT_HEIGHT;
+       int wide = bd_formats[use_standard].wide;
+       bd_aspect_width  = wide < 0 ? 1. :
+               wide > 0 ? BD_WIDE_ASPECT_WIDTH  : BD_ASPECT_WIDTH;
+       bd_aspect_height = wide < 0 ? 1. :
+               wide > 0 ? BD_WIDE_ASPECT_HEIGHT : BD_ASPECT_HEIGHT;
        bd_interlace_mode = bd_formats[use_standard].interlaced;
        double bd_aspect = bd_aspect_width / bd_aspect_height;
 
@@ -865,7 +868,8 @@ option_presets()
                                float aw, ah;
                                MWindow::create_aspect_ratio(aw, ah, w, h);
                                double aspect = ah > 0 ? aw / ah : 1;
-                               if( !EQUIV(aspect, bd_aspect) ) use_scale = Rescale::scaled;
+                               if( wide >= 0 && !EQUIV(aspect, bd_aspect) )
+                                       use_scale = Rescale::scaled;
                        }
                        for( int i=0; i<trk->plugin_set.size(); ++i ) {
                                for(Plugin *plugin = (Plugin*)trk->plugin_set[i]->first;
index e70aa69a1503549c5bc1bb03b988e43942a48264..a85967062f763cd0130f6d8e55372b355cc70e7e 100644 (file)
@@ -54,6 +54,7 @@
 #define BCTEXTLEN 1024
 #define BLURAY_TS_PKTSZ 192L
 
+static const int bd_sig = 2;
 
 extern "C" {
 #include "libavfilter/buffersrc.h"
@@ -186,15 +187,19 @@ class bs_length {
   int64_t fpos, len;
 public:
   bs_length() { fpos = len = 0; }
+  int64_t bs_posb(bs_file &bs) { return bs.posb() - fpos; }
   void bs_len(bs_file &bs, int n) {
     bs.write(len, n);  fpos = bs.posb();
   }
   void bs_end(bs_file &bs) {
-    len = bs.posb() - fpos;
+    len = bs_posb(bs);
   }
   void bs_ofs(bs_file &bs, int n) {
     bs.write(fpos-n/8, n);
   }
+  void bs_zofs(bs_file &bs, int n) {
+    bs.write(!len ? 0 : fpos-n/8, n);
+  }
 };
 
 class _bd_stream_info {
@@ -580,6 +585,15 @@ public:
   ~clpi_cpi() { remove_all_objects(); }
 };
 
+class clpi_cmrk : public bs_length {
+public:
+  int write();
+
+  clpi_cmrk() {}
+  ~clpi_cmrk() {}
+};
+
+
 class bd_uo_mask {
 public:
   unsigned int menu_call : 1;
@@ -890,7 +904,7 @@ public:
   int write_pip_metadata_extension();
   int write();
 
-  mpls_pl() { sig = 1; }
+  mpls_pl() { sig = bd_sig; }
   ~mpls_pl() {
     play_item.remove_all_objects();
     sub_path.remove_all_objects();
@@ -922,6 +936,7 @@ public:
   clpi_extents extents;
   clpi_programs programs_ss;
   clpi_cpi cpi_ss;
+  clpi_cmrk cmrk;
 
   int write_header();
   int write();
@@ -929,7 +944,7 @@ public:
   int write_clpi_extension(int id1, int id2, void *handle);
   int write_mpls_extension(int id1, int id2, void *handle);
 
-  clpi_cl() { sig = 1; }
+  clpi_cl() { sig = bd_sig; }
   ~clpi_cl() {}
 };
 
@@ -983,7 +998,7 @@ public:
   int sig;
   ArrayList<movie_obj *> movies;
 
-  movie_file() { sig = 1; }
+  movie_file() { sig = bd_sig; }
   ~movie_file() {
     movies.remove_all_objects();
   }
@@ -1062,7 +1077,7 @@ public:
   int write();
 
   index_file() {
-    sig = 1;
+    sig = bd_sig;
     memset(user_data, 0, sizeof(user_data));
   }
   ~index_file() {
@@ -1086,7 +1101,7 @@ public:
   int sig;
   int write();
 
-  bdid() { sig = 1; }
+  bdid() { sig = bd_sig; }
   ~bdid() {}
 };
 
@@ -1200,6 +1215,7 @@ public:
   ArrayList<clpi_cl *> cl;
   ArrayList<mpls_pl *> pl;
 
+  void add_movie(uint32_t *ops, int n);
   int compose();
   int write(char *fn);
 
@@ -1402,7 +1418,7 @@ index_file::write()
   bs.writeb("INDX", 4);
   bs.writeb(sig == 1 ? "0100" : "0200", 4);
   bs_ofs(bs, 32);
-  exten.bs_ofs(bs, 32);
+  exten.bs_zofs(bs, 32);
   int appinfo_start = 0x28;
   bs.posb(appinfo_start);
   appinf.bs_len(bs, 32);
@@ -1530,6 +1546,7 @@ clpi_prog_stream::write()
     return 1;
   };
 
+  bs.padb(0x15 - bs_posb(bs));
   bs_end(bs);
   return 0;
 }
@@ -1734,6 +1751,14 @@ clpi_cpi::write()
   return 0;
 }
 
+int
+clpi_cmrk::write()
+{
+  bs_len(bs, 32);
+  bs_end(bs);
+  return 0;
+}
+
 int
 clpi_extents::write()
 {
@@ -1787,6 +1812,8 @@ clpi_cl::write()
   if( programs.write() ) return 1;
   cpi_start_addr = bs.posb();
   if( cpi.write() ) return 1;
+  clip_mark_start_addr = bs.posb();
+  if( cmrk.write() ) return 1;
 //if( has_ext_data ) {
 //  ext_data_start_addr = bs.pos();
 //  bdmv_write_extension_data(write_clpi_extension, this);
@@ -1897,6 +1924,7 @@ write()
     fprintf(stderr, "unrecognized stream type %02x\n", stream_type);
     break;
   };
+  bs.padb(9 - strm.bs_posb(bs));
   strm.bs_end(bs);
 
   code.bs_len(bs, 8);
@@ -1940,6 +1968,7 @@ write()
     fprintf(stderr, "mpls_stream: unrecognized coding type %02x\n", coding_type);
     break;
   };
+  bs.padb(5 - code.bs_posb(bs));
   code.bs_end(bs);
   return 0;
 }
@@ -2303,14 +2332,20 @@ mkbdmv(char *path)
   char bdmv_path[BCTEXTLEN];
   sprintf(bdmv_path, "%s/BDMV", path);
   if( mk_bdmv_dir(bdmv_path) ) return 1;
+  char cert_path[BCTEXTLEN];
+  sprintf(cert_path, "%s/CERTIFICATE", path);
+  if( mk_bdmv_dir(cert_path) ) return 1;
+  char cert_backup[BCTEXTLEN];
+  sprintf(cert_backup, "%s/BACKUP", cert_path);
+  if( mk_bdmv_dir(cert_backup) ) return 1;
   char stream_path[BCTEXTLEN];
-  sprintf(stream_path, "%s/BDMV/STREAM", path);
+  sprintf(stream_path, "%s/STREAM", bdmv_path);
   if( mk_dir(stream_path) ) return 1;
   char auxdata_path[BCTEXTLEN];
-  sprintf(auxdata_path, "%s/BDMV/AUXDATA", path);
+  sprintf(auxdata_path, "%s/AUXDATA", bdmv_path);
   if( mk_dir(auxdata_path) ) return 1;
   char meta_path[BCTEXTLEN];
-  sprintf(meta_path, "%s/BDMV/META", path);
+  sprintf(meta_path, "%s/META", bdmv_path);
   if( mk_dir(meta_path) ) return 1;
   char backup_path[BCTEXTLEN];
   sprintf(backup_path, "%s/BACKUP", bdmv_path);
@@ -2334,15 +2369,15 @@ build_toc(clpi_ep_map_entry *map)
     uint32_t pkt = mp->pos / BLURAY_TS_PKTSZ;
     if( last_pkt >= pkt ) continue;
     last_pkt = pkt;
-    int64_t coarse_pts = (pts >> 18) & ~0x01;
+    int64_t coarse_pts = (pts >> 18); // & ~0x01;
     int64_t fine_pts = (pts & 0x7ffff) >> 8;
     uint32_t mpkt = pkt & ~0x1ffff;
-    if( !cp || cp->pts_ep != coarse_pts || cp->spn_ep != mpkt ) {
+    if( !cp || cp->pts_ep != coarse_pts || mpkt > cp->spn_ep ) {
       cp = new clpi_ep_coarse();
       map->coarse.append(cp);
       cp->ref_ep_fine_id = map->fine.size();
       cp->pts_ep = coarse_pts;
-      cp->spn_ep = mpkt;
+      cp->spn_ep = pkt;
     }
     clpi_ep_fine *fp = new clpi_ep_fine();
     map->fine.append(fp);
@@ -2362,6 +2397,8 @@ static int bd_stream_type(AVCodecID codec_id)
   int stream_type = 0;
   switch (codec_id) {
   case AV_CODEC_ID_MPEG1VIDEO:
+    stream_type = BLURAY_STREAM_TYPE_VIDEO_MPEG1;
+    break;
   case AV_CODEC_ID_MPEG2VIDEO:
     stream_type = BLURAY_STREAM_TYPE_VIDEO_MPEG2;
     break;
@@ -2369,18 +2406,26 @@ static int bd_stream_type(AVCodecID codec_id)
     stream_type = BLURAY_STREAM_TYPE_VIDEO_H264;
     break;
   case AV_CODEC_ID_MP2:
-  case AV_CODEC_ID_MP3:
     stream_type = BLURAY_STREAM_TYPE_AUDIO_MPEG1;
     break;
+  case AV_CODEC_ID_MP3:
+    stream_type = BLURAY_STREAM_TYPE_AUDIO_MPEG2;
+    break;
   case AV_CODEC_ID_AC3:
     stream_type = BLURAY_STREAM_TYPE_AUDIO_AC3;
     break;
+  case AV_CODEC_ID_EAC3:
+    stream_type = BLURAY_STREAM_TYPE_AUDIO_AC3PLUS;
+    break;
   case AV_CODEC_ID_DTS:
     stream_type = BLURAY_STREAM_TYPE_AUDIO_DTS;
     break;
   case AV_CODEC_ID_TRUEHD:
     stream_type = BLURAY_STREAM_TYPE_AUDIO_TRUHD;
     break;
+  case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
+    stream_type = BLURAY_STREAM_TYPE_SUB_PG;
+    break;
   default:
     fprintf(stderr, "unknown bluray stream type %s\n", avcodec_get_name(codec_id));
     exit(1);
@@ -2524,6 +2569,7 @@ int media_info::scan()
     switch( type ) {
     case AVMEDIA_TYPE_VIDEO: break;
     case AVMEDIA_TYPE_AUDIO: break;
+    case AVMEDIA_TYPE_SUBTITLE: break;
     default: continue;
     }
     stream *s = new stream(type, i);
@@ -2549,7 +2595,12 @@ int media_info::scan()
       s->coding_type = bd_stream_type(codec_id);
       s->format = bd_audio_format(st->codec->channels);
       s->rate = bd_audio_rate(st->codec->sample_rate);
-      strcpy((char*)s->lang, "und");
+      strcpy((char*)s->lang, "eng");
+      break; }
+    case AVMEDIA_TYPE_SUBTITLE: {
+      s->coding_type = bd_stream_type(codec_id);
+      AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", 0, 0);
+      strncpy((char*)s->lang, lang ? lang->value : "und", sizeof(s->lang));
       break; }
     default:
       break;
@@ -2574,7 +2625,7 @@ int media_info::scan()
     program *pgm = new program(-1, 1);
     pgm->ep_pid = ep_pid;
     pgm->pmt_pid = 0x1000;
-    pgm->pcr_pid = 0x100;
+    pgm->pcr_pid = 0x1001;
     pgm->duration = 0;
     for( int jj=0; jj<streams.size(); ++jj ) {
       AVStream *st = fmt_ctx->streams[jj];
@@ -2609,6 +2660,7 @@ int media_info::scan()
         if( ep_pid < 0 ) ep_pid = st->id;
         break;
       case AVMEDIA_TYPE_AUDIO:
+      case AVMEDIA_TYPE_SUBTITLE:
         break;
       default:
         continue;
@@ -2647,7 +2699,7 @@ int media_info::scan(AVFormatContext *fmt_ctx)
   int ret = 0;
   AVPacket ipkt;
   av_init_packet(&ipkt);
-#if 0
+#if 1
 // zero pts at pos zero
   for( int i=0; i<programs.size(); ++i ) {
     program *p = programs[i];
@@ -2710,29 +2762,38 @@ int media_info::scan(AVFormatContext *fmt_ctx)
   return ret != AVERROR_EOF ? -1 : 0;
 }
 
+void
+Media::add_movie(uint32_t *ops, int n)
+{
+  movie_obj *mp = new movie_obj();
+  mp->resume_intention_flag = 1;
+  uint32_t *eop = ops + n/sizeof(*ops);
+  while( ops < eop ) {
+    command_obj *cmd = new command_obj();
+    cmd->cmd = htobe32(*ops++);
+    cmd->dst = *ops++;
+    cmd->src = *ops++;
+    mp->cmds.append(cmd);
+  }
+  mov.movies.append(mp);
+}
+
 int
 Media::compose()
 {
-// index
-  bs.init();
-  idx.sig = 1;
-  idx.first_play.set_hdmv(0, pb_typ_movie);
-  idx.top_menu.set_hdmv(0xffff, pb_typ_iactv);
-
 // movie
   bs.init();
-  mov.sig = 1;
+
+// top menu
+  int top_menu_obj = mov.movies.size();
   movie_obj *mp = new movie_obj();
   mp->resume_intention_flag = 1;
   command_obj *cmd = new command_obj();
   cmd->cmd = htobe32(0x21810000); cmd->dst = 1; cmd->src = 0;
   mp->cmds.append(cmd);  // JUMP_TITLE 1
-  cmd = new command_obj();
-  cmd->cmd = htobe32(0x00020000); cmd->dst = 0; cmd->src = 0;
-  mp->cmds.append(cmd);
-  mov.movies.append(mp); // BREAK
-
+  mov.movies.append(mp);
 
+// titles
   for( int ii=0; ii<size(); ++ii ) {
     mp = new movie_obj();
     mp->resume_intention_flag = 1;
@@ -2745,15 +2806,19 @@ Media::compose()
     mov.movies.append(mp); // BREAK
   }
 
+// first play
+  int first_play_obj = mov.movies.size();
   mp = new movie_obj();
   mp->resume_intention_flag = 1;
   cmd = new command_obj();
-  cmd->cmd = htobe32(0x21810000); cmd->dst = 1; cmd->src = 0;
-  mp->cmds.append(cmd);  // JUMP_TITLE 1
-  cmd = new command_obj();
-  cmd->cmd = htobe32(0x00020000); cmd->dst = 0; cmd->src = 0;
-  mp->cmds.append(cmd);
-  mov.movies.append(mp); // BREAK
+  cmd->cmd = htobe32(0x21810000); cmd->dst = 0; cmd->src = 0;
+  mp->cmds.append(cmd);  // JUMP_TITLE 0 ; top menu
+  mov.movies.append(mp);
+
+// index
+  bs.init();
+  idx.first_play.set_hdmv(first_play_obj, pb_typ_iactv);
+  idx.top_menu.set_hdmv(top_menu_obj, pb_typ_iactv);
 
   title_obj *tp = 0;
 // clips
@@ -2776,7 +2841,7 @@ Media::compose()
     cp->clip.clip_stream_type = 1;
     cp->clip.application_type = BLURAY_APP_TYPE_MAIN_MOVIE;
     cp->clip.ts_recording_rate = ip->bit_rate;
-    uint32_t ts_pkt_count = ip->file_size / BLURAY_TS_PKTSZ + 1;
+    uint32_t ts_pkt_count = ip->file_size / BLURAY_TS_PKTSZ;
     cp->clip.num_source_packets = ts_pkt_count;
     cp->clip.ts_type_info.validity = 0x80;
     strcpy(cp->clip.ts_type_info.format_id, "HDMV");
@@ -2801,6 +2866,7 @@ Media::compose()
           s->aspect = sp->aspect;
           break;
         case AVMEDIA_TYPE_AUDIO:
+        case AVMEDIA_TYPE_SUBTITLE:
           memcpy(s->lang,sp->lang,sizeof(s->lang));
           break;
         default:
@@ -2809,6 +2875,7 @@ Media::compose()
         p->streams.append(s);
       }
       clpi_ep_map_entry *map = new clpi_ep_map_entry(pgm->ep_pid);
+      map->ep_stream_type = 1;
       pgm->build_toc(map);
       cp->cpi.append(map);
       cp->programs.append(p);
@@ -2843,6 +2910,7 @@ Media::compose()
       pgm = ip->prog();
       mpls_pi *pi = new mpls_pi();
       pi->connection_condition = 1; // seamless
+//    pi->uo_mask.xxx = 1;
       pi->in_time = pgm->start_time;
       pi->out_time = pgm->end_time;
       if( ip->still )
@@ -2857,6 +2925,7 @@ Media::compose()
         switch( sp->type ) {
         case AVMEDIA_TYPE_VIDEO: break;
         case AVMEDIA_TYPE_AUDIO: break;
+        case AVMEDIA_TYPE_SUBTITLE: break;
         default: continue;
         }
         mpls_stream *ps = new mpls_stream();
@@ -2873,6 +2942,10 @@ Media::compose()
           memcpy(ps->lang, sp->lang, sizeof(ps->lang));
           pi->stn.audio.append(ps);
           break;
+        case AVMEDIA_TYPE_SUBTITLE:
+          memcpy(ps->lang, sp->lang, sizeof(ps->lang));
+          pi->stn.pg.append(ps);
+          break;
         default:
           break;
         }
@@ -2880,7 +2953,7 @@ Media::compose()
       pp->play_item.append(pi);
     }
 // chapter marks every ch_duration ticks
-    int64_t ch_duration = 45000 * 60*10;
+    int64_t ch_duration = 45000 * 60*5;
     int64_t mrktm = ch_duration;
     int64_t plytm = 0;
     int pmark = 0, pitem = 0;
index 3ba2224468d290324c8f48da196a71ab97808efc..60a17ed49e6cb584e8a260b2ac12c8b320542593 100644 (file)
@@ -21,6 +21,7 @@
 #include "file.h"
 #include "ffmpeg.h"
 #include "indexfile.h"
+#include "interlacemodes.h"
 #include "libdv.h"
 #include "libmjpeg.h"
 #include "mainerror.h"
@@ -725,6 +726,8 @@ FFVideoStream::FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx)
        frame_rate = 0;
        aspect_ratio = 0;
        length = 0;
+       interlaced = 0;
+       top_field_first = 0;
 }
 
 FFVideoStream::~FFVideoStream()
@@ -822,6 +825,10 @@ int FFVideoStream::encode(VFrame *vframe)
 
 int FFVideoStream::encode_frame(AVPacket *pkt, AVFrame *frame, int &got_packet)
 {
+       if( frame ) {
+               frame->interlaced_frame = interlaced;
+               frame->top_field_first = top_field_first;
+       }
        int ret = avcodec_encode_video2(st->codec, pkt, frame, &got_packet);
        if( ret < 0 ) {
                ff_err(ret, "FFVideoStream::encode_frame: encode video failed\n");
@@ -1172,7 +1179,7 @@ AVRational FFMPEG::to_sample_aspect_ratio(Asset *asset)
        int width = 1000000, height = width * sample_aspect + 0.5;
        float w, h;
        MWindow::create_aspect_ratio(w, h, width, height);
-       return (AVRational){(int)h, (int)w};
+       return (AVRational){(int)w, (int)h};
 #else
 // square pixels
        return (AVRational){1, 1};
@@ -1245,20 +1252,38 @@ int FFMPEG::get_codec(char *codec, const char *path, const char *spec)
 
 int FFMPEG::get_file_format()
 {
-       int ret = 0;
+       char audio_muxer[BCSTRLEN], video_muxer[BCSTRLEN];
        char audio_format[BCSTRLEN], video_format[BCSTRLEN];
-       file_format[0] = audio_format[0] = video_format[0] = 0;
+       audio_muxer[0] = audio_format[0] = 0;
+       video_muxer[0] = video_format[0] = 0;
        Asset *asset = file_base->asset;
-       if( !ret && asset->audio_data )
-               ret = get_format(audio_format, "audio", asset->acodec);
-       if( !ret && asset->video_data )
-               ret = get_format(video_format, "video", asset->vcodec);
-       if( !ret && !audio_format[0] && !video_format[0] )
+       int ret = asset ? 0 : 1;
+       if( !ret && asset->audio_data ) {
+               if( !(ret=get_format(audio_format, "audio", asset->acodec)) ) {
+                       if( get_format(audio_muxer, "format", audio_format) ) {
+                               strcpy(audio_muxer, audio_format);
+                               audio_format[0] = 0;
+                       }
+               }
+       }
+       if( !ret && asset->video_data ) {
+               if( !(ret=get_format(video_format, "video", asset->vcodec)) ) {
+                       if( get_format(video_muxer, "format", video_format) ) {
+                               strcpy(video_muxer, video_format);
+                               video_format[0] = 0;
+                       }
+               }
+       }
+       if( !ret && !audio_muxer[0] && !video_muxer[0] )
                ret = 1;
+       if( !ret && audio_muxer[0] && video_muxer[0] &&
+           strcmp(audio_muxer, video_muxer) ) ret = -1;
        if( !ret && audio_format[0] && video_format[0] &&
            strcmp(audio_format, video_format) ) ret = -1;
        if( !ret )
-               strcpy(file_format, audio_format[0] ? audio_format : video_format);
+               strcpy(file_format, !audio_format[0] && !video_format[0] ?
+                       (audio_muxer[0] ? audio_muxer : video_muxer) :
+                       (audio_format[0] ? audio_format : video_format));
        return ret;
 }
 
@@ -1266,7 +1291,7 @@ int FFMPEG::scan_option_line(char *cp, char *tag, char *val)
 {
        while( *cp == ' ' || *cp == '\t' ) ++cp;
        char *bp = cp;
-       while( *cp && *cp != ' ' && *cp != '\t' && *cp != '=' ) ++cp;
+       while( *cp && *cp != ' ' && *cp != '\t' && *cp != '=' && *cp != '\n' ) ++cp;
        int len = cp - bp;
        if( !len || len > BCSTRLEN-1 ) return 1;
        while( bp < cp ) *tag++ = *bp++;
@@ -1287,7 +1312,7 @@ int FFMPEG::load_defaults(const char *path, const char *type,
                 char *codec, char *codec_options, int len)
 {
        char default_file[BCTEXTLEN];
-       FFMPEG::set_option_path(default_file, "%s/%s.dfl", path, type);
+       set_option_path(default_file, "%s/%s.dfl", path, type);
        FILE *fp = fopen(default_file,"r");
        if( !fp ) return 1;
        fgets(codec, BCSTRLEN, fp);
@@ -1299,14 +1324,15 @@ int FFMPEG::load_defaults(const char *path, const char *type,
                codec_options += n;  len -= n;
        }
        fclose(fp);
-       FFMPEG::set_option_path(default_file, "%s/%s", path, codec);
-       return FFMPEG::load_options(default_file, codec_options, len);
+       set_option_path(default_file, "%s/%s", path, codec);
+       return load_options(default_file, codec_options, len);
 }
 
 void FFMPEG::set_asset_format(Asset *asset, const char *text)
 {
        if( asset->format != FILE_FFMPEG ) return;
-       strcpy(asset->fformat, text);
+       if( text != asset->fformat )
+               strcpy(asset->fformat, text);
        if( !asset->ff_audio_options[0] ) {
                asset->audio_data = !load_defaults("audio", text, asset->acodec,
                        asset->ff_audio_options, sizeof(asset->ff_audio_options));
@@ -1347,11 +1373,18 @@ int FFMPEG::get_encoder(FILE *fp,
        return 0;
 }
 
-int FFMPEG::read_options(const char *options, AVDictionary *&opts)
+int FFMPEG::read_options(const char *options, AVDictionary *&opts, int skip)
 {
        FILE *fp = fopen(options,"r");
        if( !fp ) return 1;
-       int ret = read_options(fp, options, opts);
+       int ret = 0;
+       while( !ret && --skip >= 0 ) {
+               int ch = getc(fp);
+               while( ch >= 0 && ch != '\n' ) ch = getc(fp);
+               if( ch < 0 ) ret = 1;
+       }
+       if( !ret )
+               ret = read_options(fp, options, opts);
        fclose(fp);
        return ret;
 }
@@ -1373,7 +1406,6 @@ int FFMPEG::read_options(FILE *fp, const char *options, AVDictionary *&opts)
        char line[BCTEXTLEN];
        while( !ret && fgets(line, sizeof(line), fp) ) {
                line[sizeof(line)-1] = 0;
-               ++no;
                if( line[0] == '#' ) continue;
                if( line[0] == '\n' ) continue;
                char key[BCSTRLEN], val[BCTEXTLEN];
@@ -1678,7 +1710,10 @@ int FFMPEG::init_encoder(const char *filename)
        }
        ff_lock("FFMPEG::init_encoder");
        av_register_all();
-       avformat_alloc_output_context2(&fmt_ctx, 0, file_format, filename);
+       char format[BCSTRLEN];
+       if( get_format(format, "format", file_format) )
+               strcpy(format, file_format);
+       avformat_alloc_output_context2(&fmt_ctx, 0, format, filename);
        if( !fmt_ctx ) {
                eprintf(_("failed: %s\n"), filename);
                ret = 1;
@@ -1836,6 +1871,9 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                        ctx->time_base = (AVRational) { frame_rate.den, frame_rate.num };
                        st->time_base = ctx->time_base;
                        vid->writing = -1;
+                       vid->interlaced = asset->interlace_mode == ILACE_MODE_TOP_FIRST ||
+                               asset->interlace_mode == ILACE_MODE_BOTTOM_FIRST ? 1 : 0;
+                       vid->top_field_first = asset->interlace_mode == ILACE_MODE_TOP_FIRST ? 1 : 0;
                        break; }
                default:
                        eprintf(_("not audio/video, %s:%s\n"), codec_name, filename);
@@ -1985,17 +2023,51 @@ int FFMPEG::encode_activate()
                        return -1;
                }
 
+               int prog_id = 1;
+               AVProgram *prog = av_new_program(fmt_ctx, prog_id);
+               for( int i=0; i< ffvideo.size(); ++i )
+                       av_program_add_stream_index(fmt_ctx, prog_id, ffvideo[i]->fidx);
+               for( int i=0; i< ffaudio.size(); ++i )
+                       av_program_add_stream_index(fmt_ctx, prog_id, ffaudio[i]->fidx);
+               int pi = fmt_ctx->nb_programs;
+               while(  --pi >= 0 && fmt_ctx->programs[pi]->id != prog_id );
+               AVDictionary **meta = &prog->metadata;
+               av_dict_set(meta, "service_provider", "cin5", 0);
+               const char *path = fmt_ctx->filename, *bp = strrchr(path,'/');
+               if( bp ) path = bp + 1;
+               av_dict_set(meta, "title", path, 0);
+
+               if( ffaudio.size() ) {
+                       const char *ep = getenv("CIN_AUDIO_LANG"), *lp = 0;
+                       if( !ep && (lp=getenv("LANG")) ) { // some are guesses
+                               static struct { const char lc[3], lng[4]; } lcode[] = {
+                                       { "en", "eng" }, { "de", "ger" }, { "es", "spa" },
+                                       { "eu", "bas" }, { "fr", "fre" }, { "el", "gre" },
+                                       { "hi", "hin" }, { "it", "ita" }, { "ja", "jap" },
+                                       { "ko", "kor" }, { "du", "dut" }, { "pl", "pol" },
+                                       { "pt", "por" }, { "ru", "rus" }, { "sl", "slv" },
+                                       { "uk", "ukr" }, { "vi", "vie" }, { "zh", "chi" },
+                               };
+                               for( int i=sizeof(lcode)/sizeof(lcode[0]); --i>=0 && !ep; )
+                                       if( !strncmp(lcode[i].lc,lp,2) ) ep = lcode[i].lng;
+                       }
+                       char lang[4];
+                       strncpy(lang,ep,3);  lang[3] = 0;
+                       AVStream *st = ffaudio[0]->st;
+                       av_dict_set(&st->metadata,"language",lang,0);
+               }
+
                AVDictionary *fopts = 0;
                char option_path[BCTEXTLEN];
                set_option_path(option_path, "format/%s", file_format);
-               read_options(option_path, fopts);
+               read_options(option_path, fopts, 1);
                ret = avformat_write_header(fmt_ctx, &fopts);
-               av_dict_free(&fopts);
                if( ret < 0 ) {
                        ff_err(ret, "FFMPEG::encode_activate: write header failed %s\n",
                                fmt_ctx->filename);
                        return -1;
                }
+               av_dict_free(&fopts);
                encoding = 1;
        }
        return encoding;
index 91ad65a6488f9ceb15435be04e63197c3e226247..f665fa922a5b6afc9e0ce0cabdd168543c7d7431 100644 (file)
@@ -243,9 +243,8 @@ public:
        int64_t length;
        float aspect_ratio;
 
-       uint8_t *pkt_bfr;
-       int pkt_bfr_sz;
-       int64_t start_pts;
+       int interlaced;
+       int top_field_first;
 };
 
 class FFMPEG : public Thread {
@@ -272,7 +271,7 @@ public:
                char *format, char *codec, char *bsfilter, char *bsargs);
        int get_encoder(FILE *fp,
                char *format, char *codec, char *bsfilter, char *bsargs);
-       int read_options(const char *options, AVDictionary *&opts);
+       int read_options(const char *options, AVDictionary *&opts, int skip=0);
        int scan_options(const char *options, AVDictionary *&opts, AVStream *st);
        int read_options(FILE *fp, const char *options, AVDictionary *&opts);
        int load_options(const char *options, AVDictionary *&opts);
index 4d7c713b9304e202d45bd3d4ba79a51932f78c57..e99732b3f1be351a3f37e6b170cff236d87f5f55 100644 (file)
@@ -502,6 +502,7 @@ int FFMPEGConfigAudioPopup::handle_event()
        FFMPEG::load_options(option_path, asset->ff_audio_options,
                         sizeof(asset->ff_audio_options));
        popup->audio_options->update(asset->ff_audio_options);
+       popup->audio_options->set_text_row(0);
 
        char value[BCTEXTLEN];
        if( !FileFFMPEG::get_ff_option("cin_bitrate", asset->ff_audio_options, value) )
@@ -663,6 +664,7 @@ int FFMPEGConfigVideoPopup::handle_event()
        FFMPEG::load_options(option_path, asset->ff_video_options,
                         sizeof(asset->ff_video_options));
        popup->video_options->update(asset->ff_video_options);
+       popup->video_options->set_text_row(0);
 
        char value[BCTEXTLEN];
        if( !FileFFMPEG::get_ff_option("cin_quality", asset->ff_video_options, value) ) {
index fce4c09fd5833787fddf7459850de228e9fb2f8b..949de932ad505907849abf942f41342f8ba2b5b5 100644 (file)
@@ -49,9 +49,8 @@
 #include <string.h>
 
 
-#define WIDTH 600
-#define HEIGHT 400
-
+#define WIDTH 640
+#define HEIGHT 425
 
 New::New(MWindow *mwindow)
  : BC_MenuItem(_("New Project..."), "n", 'n')
@@ -163,8 +162,8 @@ BC_Window* NewThread::new_gui()
        load_defaults();
 
        mwindow->gui->lock_window("NewThread::new_gui");
-       int x = mwindow->gui->get_abs_cursor_x(0) - WIDTH / 2;
-       int y = mwindow->gui->get_abs_cursor_y(0) - HEIGHT / 2;
+       int x = mwindow->gui->get_pop_cursor_x(0);
+       int y = mwindow->gui->get_pop_cursor_y(0);
 
        nwindow = new NewWindow(mwindow, this, x, y);
        nwindow->create_objects();
@@ -177,6 +176,7 @@ BC_Window* NewThread::new_gui()
 void NewThread::handle_close_event(int result)
 {
 
+       if( !new_project->new_edl ) return;
        new_project->new_edl->save_defaults(mwindow->defaults);
        mwindow->defaults->save();
 
@@ -227,16 +227,8 @@ int NewThread::update_aspect()
 
 
 NewWindow::NewWindow(MWindow *mwindow, NewThread *new_thread, int x, int y)
- : BC_Window(_(_(PROGRAM_NAME ": New Project")),
-               x,
-               y,
-               WIDTH,
-               HEIGHT,
-               -1,
-               -1,
-               0,
-               0,
-               1)
+ : BC_Window(_(PROGRAM_NAME ": New Project"), x, y, WIDTH, HEIGHT,
+               -1, -1, 0, 0, 1)
 {
        this->mwindow = mwindow;
        this->new_thread = new_thread;
@@ -306,7 +298,7 @@ void NewWindow::create_objects()
        y += 30;
        x1 = x;
        add_subwindow(new BC_Title(x1, y, _("Tracks:")));
-       x1 += 100;
+       x1 += 115;
        add_subwindow(vtracks = new NewVTracks(this, "", x1, y));
        x1 += vtracks->get_w();
        add_subwindow(new NewVTracksTumbler(this, x1, y));
@@ -321,7 +313,7 @@ void NewWindow::create_objects()
 //     y += vchannels->get_h() + 5;
        x1 = x;
        add_subwindow(new BC_Title(x1, y, _("Framerate:")));
-       x1 += 100;
+       x1 += 115;
        add_subwindow(frame_rate = new NewFrameRate(this, "", x1, y));
        x1 += frame_rate->get_w();
        add_subwindow(new FrameRatePulldown(mwindow, frame_rate, x1, y));
@@ -347,7 +339,7 @@ void NewWindow::create_objects()
 
        x1 = x;
        add_subwindow(new BC_Title(x1, y, _("Canvas size:")));
-       x1 += 100;
+       x1 += 115;
        add_subwindow(output_w_text = new NewOutputW(this, x1, y));
        x1 += output_w_text->get_w() + 2;
        add_subwindow(new BC_Title(x1, y, "x"));
@@ -360,13 +352,13 @@ void NewWindow::create_objects()
                output_h_text,
                x1,
                y));
-       x1 += pulldown->get_w() + 5;
+       x1 += pulldown->get_w() + 10;
        add_subwindow(new NewSwapExtents(mwindow, this, x1, y));
        y += output_h_text->get_h() + 5;
 
        x1 = x;
        add_subwindow(new BC_Title(x1, y, _("Aspect ratio:")));
-       x1 += 100;
+       x1 += 115;
        add_subwindow(aspect_w_text = new NewAspectW(this, "", x1, y));
        x1 += aspect_w_text->get_w() + 2;
        add_subwindow(new BC_Title(x1, y, ":"));
@@ -383,25 +375,23 @@ void NewWindow::create_objects()
        y += aspect_w_text->get_h() + 5;
        add_subwindow(new NewAspectAuto(this, x1, y));
        y += 40;
-       add_subwindow(new BC_Title(x, y, _("Color model:")));
-       add_subwindow(textbox = new BC_TextBox(x + 100, y, 200, 1, ""));
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x, y, _("Color model:")));
+       x1 = x + title->get_w();
+       y1 = y;  y += title->get_h() + 10;
+       add_subwindow(title = new BC_Title(x, y, _("Interlace mode:")));
+       int x2 = x + title->get_w();
+       int y2 = y;  y += title->get_h() + 10;
+       if( x1 < x2 ) x1 = x2;
+       x1 += 20;
+       add_subwindow(textbox = new BC_TextBox(x1, y1, 150, 1, ""));
        add_subwindow(color_model = new ColormodelPulldown(mwindow,
-               textbox,
-               &new_edl->session->color_model,
-               x + 100 + textbox->get_w(),
-               y));
-       y += textbox->get_h() + 5;
-
-       // --------------------
-       add_subwindow(new BC_Title(x, y, _("Interlace mode:")));
-       add_subwindow(textbox = new BC_TextBox(x + 100, y, 140, 1, ""));
+               textbox, &new_edl->session->color_model, x1+textbox->get_w(), y1));
+       add_subwindow(textbox = new BC_TextBox(x1, y2, 150, 1, ""));
        add_subwindow(interlace_pulldown = new InterlacemodePulldown(mwindow,
-               textbox,
-               &new_edl->session->interlace_mode,
+               textbox, &new_edl->session->interlace_mode,
                (ArrayList<BC_ListBoxItem*>*)&mwindow->interlace_project_modes,
-               x + 100 + textbox->get_w(),
-               y));
-       y += textbox->get_h() + 5;
+               x1+textbox->get_w(), y2));
 
        add_subwindow(new BC_OKButton(this,
                mwindow->theme->get_image_set("new_ok_images")));
index 1f76a92a25363539f7dedb0d0cb579a9ffc59ce4..d6db3811469629a999d44d1889e91b66d1475673 100644 (file)
@@ -336,13 +336,10 @@ BC_Window* Render::new_gui()
                if(!asset) asset = new Asset;
                load_defaults(asset);
                check_asset(mwindow->edl, *asset);
-
+               int px = mwindow->gui->get_pop_cursor_x(1);
+               int py = mwindow->gui->get_pop_cursor_y(1);
 // Get format from user
-               render_window = new RenderWindow(mwindow,
-                       this,
-                       asset,
-                       mwindow->gui->get_abs_cursor_x(1),
-                       mwindow->gui->get_abs_cursor_y(1));
+               render_window = new RenderWindow(mwindow, this, asset, px, py);
                render_window->create_objects();
        }
 
@@ -1108,10 +1105,8 @@ RenderWindow::RenderWindow(MWindow *mwindow,
        Asset *asset,
        int x,
        int y)
- : BC_Window(_(PROGRAM_NAME ": Render"),
-       x - WIDTH / 2, y - HEIGHT / 2,
-       WIDTH, HEIGHT, WIDTH, HEIGHT,
-       0, 0, 1)
+ : BC_Window(_(PROGRAM_NAME ": Render"), x, y,
+       WIDTH, HEIGHT, WIDTH, HEIGHT, 0, 0, 1)
 {
        this->mwindow = mwindow;
        this->render = render;
index 40ac01b39bd9b209892bc35961aab8d562d9cef2..8f8b3c6869a003682b102e888ab2bfcdb5789b36 100644 (file)
@@ -764,7 +764,7 @@ if test  $WANT_X264_HIDEPTH = "yes" ; then
   echo "x264.cfg_params := --enable-static --bit-depth=10"
 fi
 if test  $WANT_X265_HIDEPTH = "yes" ; then
-  echo "x265.cfg_params := -DENABLE_SHARED=no -DHIGH_BIT_DEPTH:BOOL=ON"
+  echo "x265.cfg_params := -DENABLE_SHARED=no -DHIGH_BIT_DEPTH:BOOL=ON -DMAIN12:BOOL=ON"
 fi
 
 for pkg in $STATIC_PKGS; do echo "static_pkgs += $pkg"; done
index 45fd78be92f13cfdbfc052ae8a247367cff7fff2..6408df920911ba4ffb593df0e47d7a0e6cafcf70 100644 (file)
@@ -1,4 +1,4 @@
-mpegts ac3
+bluray ac3
 id 0x1100
 maxrate 9000000
 minrate 0
diff --git a/cinelerra-5.1/ffmpeg/format/bluray b/cinelerra-5.1/ffmpeg/format/bluray
new file mode 100644 (file)
index 0000000..292b00c
--- /dev/null
@@ -0,0 +1,7 @@
+mpegts
+mpegts_m2ts_mode=2
+mpegts_pmt_start_pid=256
+sdt_period=-1
+packetsize 2048
+muxrate 10080000
+preload 500000
index 8e3012b905579b748d3a5998ecd4393775724d4f..f24dccd88a7da907db98ecfe7c7c480a9d209755 100644 (file)
@@ -156,6 +156,7 @@ swapuv
 #tblend
 #telecine
 #testsrc
+#testsrc2
 #thumbnail
 #tile
 #tinterlace
index a388e6f345f8c957b584c957b2c4d776d8d95248..4271cd627855a4ed225c30bc3bd7c70827e475f9 100644 (file)
@@ -1,8 +1,15 @@
-mpegts libx264
+bluray libx264
+bluray-compat=1
 id=0x1011
+level=41
+bf=2
+refs=3
+color_range=mpeg
+colorspace=bt709
+color_trc=bt709
+color_primaries=bt709
 profile=high422
-pixel_format=yuv422p
-level=3.0
 preset=medium
-bluray-compat=1
+pixel_format=yuv422p
+flags=+cgop
 x264opts keyint=25:min-keyint=4:qpmin=3:qpmax=33:qp_step=4:merange=8
index d484e8ec8358671a8342d21314260764df19d485..51112c9c1afdc3dfce58e502e8a4293d7f8aad5d 100644 (file)
@@ -1,8 +1,15 @@
-mpegts libx264
+bluray libx264
+bluray-compat=1
 id=0x1011
+level=41
+bf=2
+refs=3
+color_range=mpeg
+colorspace=bt709
+color_trc=bt709
+color_primaries=bt709
 profile=high
-level=3.0
 preset=medium
-bluray-compat=1
+flags=+cgop
 # must be last for bdcreate.C
 x264opts keyint=25:min-keyint=4:qpmin=3:qpmax=33:qp_step=4:merange=8
index 90de1b93317e6a96d1ff8bb5c0bf559947a8f6fa..68c4254547fad2a6fb9d6c11bfa308a16ce61b48 100644 (file)
@@ -1,7 +1,14 @@
-mpegts libx264
+bluray libx264
+bluray-compat=1
 id=0x1011
+level=41
+bf=2
+refs=3
+color_range=mpeg
+colorspace=bt709
+color_trc=bt709
+color_primaries=bt709
 profile=baseline
-level=3.0
 preset=medium
-bluray-compat=1
+flags=+cgop
 x264opts keyint=25:min-keyint=4:qpmin=3:qpmax=33:qp_step=4:merange=8
diff --git a/cinelerra-5.1/ffmpeg/video/h265-12bit.mp4 b/cinelerra-5.1/ffmpeg/video/h265-12bit.mp4
new file mode 100644 (file)
index 0000000..3d42dbb
--- /dev/null
@@ -0,0 +1,9 @@
+mp4 libx265
+# only works in build cinx hi-depth build
+strict=-2
+colorspace=bt2020_cl
+color_primaries=bt2020
+color_trc=bt2020_12bit
+pixel_format=yuv422p12
+x265-params=output-depth=12
+
similarity index 66%
rename from cinelerra-5.1/ffmpeg/video/h265.mp4
rename to cinelerra-5.1/ffmpeg/video/h265-hi.mp4
index d045e2339663c0871dd8e5e54aeb0355af693c10..8e2a09d661f32bc06f0814e57f8c5da4873963e2 100644 (file)
@@ -1 +1,2 @@
 mp4 libx265
+crf=5
diff --git a/cinelerra-5.1/ffmpeg/video/h265-lo.mp4 b/cinelerra-5.1/ffmpeg/video/h265-lo.mp4
new file mode 100644 (file)
index 0000000..1bbf933
--- /dev/null
@@ -0,0 +1,3 @@
+mp4 libx265
+# lossy but faster
+crf=25
diff --git a/cinelerra-5.1/ffmpeg/video/h265-med.mp4 b/cinelerra-5.1/ffmpeg/video/h265-med.mp4
new file mode 100644 (file)
index 0000000..b8b9375
--- /dev/null
@@ -0,0 +1,3 @@
+mp4 libx265
+# visually lossless
+crf=18
index effb81a565cf2e9fdc9c4d8cd3615fd782545449..f15e594a34870ce2ee673cde3e6ab191e38c5196 100644 (file)
@@ -1,9 +1,8 @@
-mpegts libx265
-loglevel=debug
+bluray libx265
 id=0x1011
 #preset=ultrafast,superfast,veryfast,faster,fast,
 #preset=medium,slow,slower,veryslow,placebo
 preset=medium
 #tune=psnr,ssim,grain,zerolatency,fastdecode
 pixel_format=yuv422p10
-x265_opts=output-depth=10
+x265_opts=profile=main10:output-depth=10
index 0496a829289f15a5816c9ea8b6548995313d3898..90f7c11b5a4b8d007800876ea612f603694465af 100644 (file)
@@ -1,9 +1,8 @@
 mpegts libx265
-loglevel=debug
 id=0x1011
 #preset=ultrafast,superfast,veryfast,faster,fast,
 #preset=medium,slow,slower,veryslow,placebo
 preset=medium
 #tune=psnr,ssim,grain,zerolatency,fastdecode
 pixel_format=yuv422p
-x265_opts=output-depth=8
+x265_opts=profile=main:output-depth=8
index 8ba87569a1e16876600c8110c0fa90eccb4b3beb..316ad72b542a478278459c582b2e2de3c3674cec 100644 (file)
@@ -1,2 +1,4 @@
 mpegts libx264
+cin_bitrate=0
+cin_quality=0
 qp=0
diff --git a/cinelerra-5.1/ffmpeg/video/visually_lossless.m2ts b/cinelerra-5.1/ffmpeg/video/visually_lossless.m2ts
new file mode 100644 (file)
index 0000000..db41439
--- /dev/null
@@ -0,0 +1,19 @@
+bluray libx264
+bluray-compat=1
+id=0x1011
+crf=18
+maxrate=20000000
+bufsize=20000000
+cin_bitrate=20000000
+cin_quality=0
+preset=medium
+level=41
+bf=2
+refs=3
+color_range=mpeg
+colorspace=bt709
+color_trc=bt709
+color_primaries=bt709
+flags=+cgop
+# must be last for bdcreate.C
+x264opts keyint=25:min-keyint=4:qpmin=3:qpmax=33:qp_step=4:merange=8
index 7baaedb3454e8a8538eef245a7faf3146c4c8beb..7d52d98c9e56250266cae06a4104132f17b3597e 100644 (file)
@@ -215,7 +215,7 @@ int BC_FileBoxDirectoryText::handle_event()
        while( *cp ) ++cp;
        if( cp > path && *--cp != '/' ) return 0;
        char *file_path = FileSystem::basepath(path);
-       char *dir_path = FileSystem::basepath(filebox->fs->get_current_dir());
+       char *dir_path = FileSystem::basepath(filebox->directory);
        int ret = !strcmp(file_path, dir_path) ? 0 : 1;
        if( ret ) {
                strcpy(filebox->directory, file_path);
@@ -497,7 +497,7 @@ BC_FileBox::BC_FileBox(int x, int y, const char *init_path,
        this->want_directory = want_directory;
        if(show_all_files) fs->set_show_all();
        fs->complete_path(this->current_path);
-       fs->complete_path(this->submitted_path);
+       strcpy(this->submitted_path, this->current_path);
        fs->extract_dir(directory, this->current_path);
        fs->extract_name(filename, this->current_path);
 
@@ -535,16 +535,12 @@ BC_FileBox::BC_FileBox(int x, int y, const char *init_path,
 // Test if current directory exists
        if(!fs->is_dir(directory))
        {
-               sprintf(this->current_path, "~");
-               fs->complete_path(this->current_path);
-               fs->set_current_dir(this->current_path);
-//             fs->update(this->current_path);
-               strcpy(directory, fs->get_current_dir());
+               sprintf(directory, "~");
+               fs->complete_path(directory);
+               strcpy(current_path,directory);
                filename[0] = 0;
        }
-       else
-               fs->set_current_dir(this->directory);
-
+       fs->set_current_dir(directory);
 
        if(h_padding == -1)
        {
@@ -592,10 +588,6 @@ void BC_FileBox::create_objects()
                fs->set_filter(get_resources()->filebox_filter);
        }
 
-       fs->set_sort_order(sort_order);
-       fs->set_sort_field(column_type[sort_column]);
-       fs->update(directory);
-
        create_icons();
        create_tables();
 
@@ -653,8 +645,12 @@ void BC_FileBox::create_objects()
        if( newest >= 0 ) {
                strcpy(directory, resources->filebox_history[newest].path);
                fs->change_dir(directory, 0);
+               strcpy(directory, fs->get_current_dir());
                directory_title->update(fs->get_current_dir());
        }
+       fs->set_sort_order(sort_order);
+       fs->set_sort_field(column_type[sort_column]);
+       fs->update(directory);
 
 // Create recent dir list
        create_history();
@@ -678,7 +674,7 @@ void BC_FileBox::create_objects()
 
        rename_thread = new BC_RenameThread(this);
 
-
+       refresh();
        show_window();
 }
 
index c76f67ef0a3fa653a6cc538f082162c270d026e5..5a9cac03f0c1dc783036e6326caa01b1f7c9e711 100644 (file)
@@ -766,6 +766,8 @@ void BC_TextBox::draw(int flush)
                                draw_wtext(text_x, k + text_ascent, wtext_row, len,
                                        0, &positions[wtext_row - wtext]);
                        }
+                       else
+                               positions[wtext_row - wtext] = 0;
 
 // Get ibeam location
                        if(ibeam_letter >= row_begin && ibeam_letter <= row_end) {
@@ -778,14 +780,8 @@ void BC_TextBox::draw(int flush)
 
 //printf("BC_TextBox::draw 3 %d\n", ibeam_y);
        if(need_ibeam) {
-               if( wtext_len == 0 ) {
-                       ibeam_x = 0;
-                       ibeam_y = 0;
-               }
-               else {
-                       ibeam_x = -1;
-                       ibeam_y = -1;
-               }
+//             ibeam_x = ibeam_y = !wtext_len ? 0 : -1;
+               ibeam_x = 0;  ibeam_y = k - text_y;
        }
 
 //printf("BC_TextBox::draw 4 %d\n", ibeam_y);
@@ -1853,9 +1849,8 @@ void BC_TextBox::get_ibeam_position(int &x, int &y)
 {
        int i, row_begin, row_end;
        int wtext_len = wtext_update();
+       x = y = 0;
 
-       y = 0;
-       x = 0;
        for( i=0; i<wtext_len; ) {
                row_begin = i;
                for(; i<wtext_len && wtext[i]!='\n'; i++);
@@ -2284,7 +2279,7 @@ void BC_ScrollTextBox::create_objects()
        parent_window->add_subwindow(yscroll = new BC_ScrollTextBoxYScroll(this));
        text->yscroll = yscroll;
        yscroll->bound_to = text;
-
+       set_text_row(0);
 }
 
 int BC_ScrollTextBox::handle_event()
index 75e37fb472633a6db03eb7a0d88293d39021a137..7d4fa2b56185dd047d93dc101f5d58546828d810 100644 (file)
@@ -2886,27 +2886,21 @@ int BC_WindowBase::get_text_width(int font, const char *text, int length)
 
 int BC_WindowBase::get_text_width(int font, const wchar_t *text, int length)
 {
-       int i, j, w = 0, line_w = 0;
-
-       if(length < 0) length = wcslen(text);
-
-       for(i = 0, j = 0; i <= length; i++)
-       {
-               line_w = 0;
-               if(text[i] == '\n')
-               {
-                       line_w = get_single_text_width(font, &text[j], i - j);
-                       j = i + 1;
+       int i, j, w = 0;
+       if( length < 0 ) length = wcslen(text);
+
+       for( i=j=0; i<length && text[i]; ++i ) {
+               if( text[i] != '\n' ) continue;
+               if( i > j ) {
+                       int lw = get_single_text_width(font, &text[j], i-j);
+                       if( w < lw ) w = lw;
                }
-               else
-               if(text[i] == 0)
-                       line_w = get_single_text_width(font, &text[j], length - j);
-
-               if(line_w > w) w = line_w;
+               j = i + 1;
+       }
+       if( j < length ) {
+               int lw = get_single_text_width(font, &text[j], length-j);
+               if( w < lw ) w = lw;
        }
-
-       if(i > length && w == 0)
-               w = get_single_text_width(font, text, length);
 
        return w;
 }
@@ -3696,6 +3690,26 @@ int BC_WindowBase::get_abs_cursor_y(int lock_window)
        return abs_y;
 }
 
+int BC_WindowBase::get_pop_cursor_x(int lock_window)
+{
+       int margin = 100;
+       int px = get_abs_cursor_x(lock_window);
+       if( px < margin ) px = margin;
+       int wd = get_screen_w(lock_window,-1) - margin;
+       if( px > wd ) px = wd;
+       return px;
+}
+
+int BC_WindowBase::get_pop_cursor_y(int lock_window)
+{
+       int margin = 100;
+       int py = get_abs_cursor_y(lock_window);
+       if( py < margin ) py = margin;
+       int ht = get_screen_h(lock_window,-1) - margin;
+       if( py > ht ) py = ht;
+       return py;
+}
+
 int BC_WindowBase::match_window(Window win)
 {
        if (this->win == win) return 1;
index 2acfe5c3b9b6006d5bbd43fd493b64702cdfdab5..4136b110fb8b423fe147d47847c0aafd242d9621 100644 (file)
@@ -281,6 +281,8 @@ public:
 // Get current position
        int get_abs_cursor_x(int lock_window);
        int get_abs_cursor_y(int lock_window);
+       int get_pop_cursor_x(int lock_window);
+       int get_pop_cursor_y(int lock_window);
        int get_relative_cursor_x();
        int get_relative_cursor_y();
        void get_root_coordinates(int x, int y, int *abs_x, int *abs_y);
index 43b75778496d688e9740c30947bca0b3f3c33460..7a47887ee8445d90be36c6441c30b4b50926dd38 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_blond/data/new_bg.png and b/cinelerra-5.1/plugins/theme_blond/data/new_bg.png differ
index 33d12eccddcca105ac110e67764ee13f8e890483..b3bbd1e134687e469662dbeb5c45395bf8c1f487 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_blond_cv/data/new_bg.png and b/cinelerra-5.1/plugins/theme_blond_cv/data/new_bg.png differ
index a5269f579b91dc67aa12e1eb80cdb1298d9464da..0d24e024178f35fe684f94f2f313563389ef4bb5 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_blue/data/new_bg.png and b/cinelerra-5.1/plugins/theme_blue/data/new_bg.png differ
index f36686483497d1ad1c014df96e90deb864753701..aac3a476165faf0f327a49759ea0544bab587431 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_blue_dot/data/new_bg.png and b/cinelerra-5.1/plugins/theme_blue_dot/data/new_bg.png differ
index d678a7015e454b0ab45851cb03ca460623be3298..a4b9cb70cb9f3a0edad5e905dd1bdfafa3acc1fb 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_bright/data/new_bg.png and b/cinelerra-5.1/plugins/theme_bright/data/new_bg.png differ
index 10d1dad1b1268e4e8f046e647aea04b881e27f0e..d5485436ecd187cc976702d318fb55aa88c2b6c1 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_hulk/data/new_bg.png and b/cinelerra-5.1/plugins/theme_hulk/data/new_bg.png differ
index cb78e3780af72b534f99a9e28688e95d1c9459f2..74291ebe2054084e461ad6aa3518a0c18f850ac5 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_pinklady/data/new_bg.png and b/cinelerra-5.1/plugins/theme_pinklady/data/new_bg.png differ
index f9f6730c9547035a0e7206b8e37dfb5541296fa2..07a5914820c6795d2b861a9bba86cf37c7ec692c 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_suv/data/new_bg.png and b/cinelerra-5.1/plugins/theme_suv/data/new_bg.png differ
index c1482cb4344a39631f262f4d74871372205b0d0f..e27a20f4341d9bf8fa7988f018b993219a8d9880 100644 (file)
Binary files a/cinelerra-5.1/plugins/theme_unflat/data/new_bg.png and b/cinelerra-5.1/plugins/theme_unflat/data/new_bg.png differ
diff --git a/cinelerra-5.1/thirdparty/src/ffmpeg.patch4 b/cinelerra-5.1/thirdparty/src/ffmpeg.patch4
new file mode 100644 (file)
index 0000000..cd7c425
--- /dev/null
@@ -0,0 +1,261 @@
+--- a/libavformat/mpegtsenc.c  2016-09-30 19:12:42.000000000 -0600
++++ b/libavformat/mpegtsenc.c  2017-01-25 17:25:58.720017593 -0700
+@@ -55,7 +55,7 @@
+     int sid;           /* service ID */
+     char *name;
+     char *provider_name;
+-    int pcr_pid;
++    int pcr_sid, pcr_pid;
+     int pcr_packet_count;
+     int pcr_packet_period;
+     AVProgram *program;
+@@ -94,8 +94,10 @@
+     int service_type;
+     int pmt_start_pid;
++    int pcr_start_pid;
+     int start_pid;
+     int m2ts_mode;
++    int64_t pcr_offset;
+     int reemit_pat_pmt; // backward compatibility
+@@ -704,6 +706,7 @@
+     service->pmt.pid       = ts->pmt_start_pid + ts->nb_services;
+     service->sid           = sid;
+     service->pcr_pid       = 0x1fff;
++    service->pcr_sid       = 0x1fff;
+     service->provider_name = av_strdup(provider_name);
+     service->name          = av_strdup(name);
+     if (!service->provider_name || !service->name)
+@@ -722,7 +725,7 @@
+ static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
+ {
+     return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
+-           ts->first_pcr;
++           ts->first_pcr + ts->pcr_offset;
+ }
+ static void mpegts_prefix_m2ts_header(AVFormatContext *s)
+@@ -760,6 +763,14 @@
+     if (s->max_delay < 0) /* Not set by the caller */
+         s->max_delay = 0;
++    if (ts->m2ts_mode == -1) {
++        if (av_match_ext(s->filename, "m2ts")) {
++            ts->m2ts_mode = 1;
++        } else {
++            ts->m2ts_mode = 0;
++        }
++    }
++
+     // round up to a whole number of TS packets
+     ts->pes_payload_size = (ts->pes_payload_size + 14 + 183) / 184 * 184 - 14;
+@@ -803,6 +814,8 @@
+             service->program          = program;
+         }
+     }
++    if (ts->m2ts_mode > 1)
++        service->pmt.pid = 0x00ff + ts->service_id;
+     ts->pat.pid          = PAT_PID;
+     /* Initialize at 15 so that it wraps and is equal to 0 for the
+@@ -885,10 +898,9 @@
+         ts_st->cc              = 15;
+         /* update PCR pid by using the first video stream */
+         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+-            service->pcr_pid == 0x1fff) {
+-            service->pcr_pid = ts_st->pid;
++            service->pcr_sid == 0x1fff)
+             pcr_st           = st;
+-        }
++
+         if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
+             st->codecpar->extradata_size > 0) {
+             AVStream *ast;
+@@ -924,12 +936,24 @@
+     av_freep(&pids);
+     /* if no video stream, use the first stream as PCR */
+-    if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
+-        pcr_st           = s->streams[0];
+-        ts_st            = pcr_st->priv_data;
+-        service->pcr_pid = ts_st->pid;
+-    } else
+-        ts_st = pcr_st->priv_data;
++    if (!pcr_st && s->nb_streams > 0)
++        pcr_st = s->streams[0];
++    if (!pcr_st) {
++        av_log(s, AV_LOG_ERROR, "no streams\n");
++        ret = AVERROR(EINVAL);
++        goto fail;
++    }
++    ts_st  = pcr_st->priv_data;
++    if (service->pcr_sid == 0x1fff)
++        service->pcr_sid   = ts_st->pid;
++    if (service->pcr_pid == 0x1fff)
++        service->pcr_pid   = ts->m2ts_mode > 1 ?
++            0x1000 + ts->service_id : service->pcr_sid ;
++    if (service->pmt.pid == service->pcr_pid) {
++        av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", service->pcr_pid);
++        ret = AVERROR(EINVAL);
++        goto fail;
++    }
+     if (ts->mux_rate > 1) {
+         service->pcr_packet_period = (int64_t)ts->mux_rate * ts->pcr_period /
+@@ -989,14 +1013,6 @@
+            service->pcr_packet_period,
+            ts->sdt_packet_period, ts->pat_packet_period);
+-    if (ts->m2ts_mode == -1) {
+-        if (av_match_ext(s->filename, "m2ts")) {
+-            ts->m2ts_mode = 1;
+-        } else {
+-            ts->m2ts_mode = 0;
+-        }
+-    }
+-
+     return 0;
+ fail:
+@@ -1010,9 +1026,9 @@
+     MpegTSWrite *ts = s->priv_data;
+     int i;
+-    if (++ts->sdt_packet_count == ts->sdt_packet_period ||
++    if ( ts->sdt_period >= 0 && (++ts->sdt_packet_count == ts->sdt_packet_period ||
+         (dts != AV_NOPTS_VALUE && ts->last_sdt_ts == AV_NOPTS_VALUE) ||
+-        (dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0)
++        (dts != AV_NOPTS_VALUE && dts - ts->last_sdt_ts >= ts->sdt_period*90000.0))
+     ) {
+         ts->sdt_packet_count = 0;
+         if (dts != AV_NOPTS_VALUE)
+@@ -1067,13 +1083,14 @@
+ {
+     MpegTSWrite *ts = s->priv_data;
+     MpegTSWriteStream *ts_st = st->priv_data;
++    uint32_t pcr_pid = ts_st->service->pcr_pid;
+     uint8_t *q;
+     uint8_t buf[TS_PACKET_SIZE];
+     q    = buf;
+     *q++ = 0x47;
+-    *q++ = ts_st->pid >> 8;
+-    *q++ = ts_st->pid;
++    *q++ = pcr_pid >> 8;
++    *q++ = pcr_pid;
+     *q++ = 0x20 | ts_st->cc;   /* Adaptation only */
+     /* Continuity Count field does not increment (see 13818-1 section 2.4.3.3) */
+     *q++ = TS_PACKET_SIZE - 5; /* Adaptation Field Length */
+@@ -1148,7 +1165,7 @@
+     uint8_t buf[TS_PACKET_SIZE];
+     uint8_t *q;
+     int val, is_start, len, header_len, write_pcr, is_dvb_subtitle, is_dvb_teletext, flags;
+-    int afc_len, stuffing_len;
++    int afc_len, stuffing_len, write_null;
+     int64_t pcr = -1; /* avoid warning */
+     int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
+     int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
+@@ -1163,8 +1180,8 @@
+         retransmit_si_info(s, force_pat, dts);
+         force_pat = 0;
+-        write_pcr = 0;
+-        if (ts_st->pid == ts_st->service->pcr_pid) {
++        write_pcr = write_null = 0;
++        if (ts_st->pid == ts_st->service->pcr_sid) {
+             if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames
+                 ts_st->service->pcr_packet_count++;
+             if (ts_st->service->pcr_packet_count >=
+@@ -1173,15 +1190,17 @@
+                 write_pcr = 1;
+             }
+         }
+-
+         if (ts->mux_rate > 1 && dts != AV_NOPTS_VALUE &&
+-            (dts - get_pcr(ts, s->pb) / 300) > delay) {
+-            /* pcr insert gets priority over null packet insert */
+-            if (write_pcr)
+-                mpegts_insert_pcr_only(s, st);
+-            else
+-                mpegts_insert_null_packet(s);
+-            /* recalculate write_pcr and possibly retransmit si_info */
++               (dts - get_pcr(ts, s->pb) / 300) > delay) {
++            write_null = 1;
++        }
++        /* pcr insert gets priority over null packet insert */
++        if (write_pcr && ts_st->service->pcr_sid != ts_st->service->pcr_pid) {
++            mpegts_insert_pcr_only(s, st);
++            continue;
++        }
++        if (write_null) {
++            mpegts_insert_null_packet(s);
+             continue;
+         }
+@@ -1191,13 +1210,17 @@
+         val  = ts_st->pid >> 8;
+         if (is_start)
+             val |= 0x40;
++        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
++          st->codecpar->codec_id == AV_CODEC_ID_AC3 &&
++          ts->m2ts_mode > 1)
++            val |= 0x20;
+         *q++      = val;
+         *q++      = ts_st->pid;
+         ts_st->cc = ts_st->cc + 1 & 0xf;
+         *q++      = 0x10 | ts_st->cc; // payload indicator + CC
+         if (key && is_start && pts != AV_NOPTS_VALUE) {
+             // set Random Access for key frames
+-            if (ts_st->pid == ts_st->service->pcr_pid)
++            if (ts_st->pid == ts_st->service->pcr_sid)
+                 write_pcr = 1;
+             set_af_flag(buf, 0x40);
+             q = get_ts_payload_start(buf);
+@@ -1310,11 +1333,13 @@
+             *q++ = flags;
+             *q++ = header_len;
+             if (pts != AV_NOPTS_VALUE) {
+-                write_pts(q, flags >> 6, pts);
++                int64_t ts_pts = pts + ts->pcr_offset;
++                write_pts(q, flags >> 6, ts_pts);
+                 q += 5;
+             }
+             if (dts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE && dts != pts) {
+-                write_pts(q, 1, dts);
++                int64_t ts_dts = dts + ts->pcr_offset;
++                write_pts(q, 1, ts_dts);
+                 q += 5;
+             }
+             if (pes_extension && st->codecpar->codec_id == AV_CODEC_ID_DIRAC) {
+@@ -1838,12 +1863,18 @@
+     { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
+       offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT,
+       { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
++    { "mpegts_pcr_start_pid", "Set the first pid of the PCR.",
++      offsetof(MpegTSWrite, pcr_start_pid), AV_OPT_TYPE_INT,
++      { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
+     { "mpegts_start_pid", "Set the first pid.",
+       offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT,
+       { .i64 = 0x0100 }, 0x0020, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
+     { "mpegts_m2ts_mode", "Enable m2ts mode.",
+       offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_BOOL,
+-      { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM },
++      { .i64 = -1 }, -1, 2, AV_OPT_FLAG_ENCODING_PARAM },
++    { "mpegts_pcr_offset", "clock offset.",
++      offsetof(MpegTSWrite, pcr_offset), AV_OPT_TYPE_BOOL,
++      { .i64 = 0 }, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+     { "muxrate", NULL,
+       offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT,
+       { .i64 = 1 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+@@ -1886,7 +1917,7 @@
+       { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+     { "sdt_period", "SDT retransmission time limit in seconds",
+       offsetof(MpegTSWrite, sdt_period), AV_OPT_TYPE_DOUBLE,
+-      { .dbl = INT_MAX }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
++      { .dbl = INT_MAX }, -1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+     { NULL },
+ };