X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fbdwrite.C;h=6a2b4ca3cb4b9bcec54d7b8620a74b51cafd7395;hp=e70aa69a1503549c5bc1bb03b988e43942a48264;hb=7e5a0760f40ff787cc3d93cb7768a901ebe52809;hpb=7c199a42936462d662ee405fe0b4df5ac74850dc diff --git a/cinelerra-5.1/cinelerra/bdwrite.C b/cinelerra-5.1/cinelerra/bdwrite.C index e70aa69a..6a2b4ca3 100644 --- a/cinelerra-5.1/cinelerra/bdwrite.C +++ b/cinelerra-5.1/cinelerra/bdwrite.C @@ -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 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() {} }; @@ -1095,17 +1110,18 @@ public: int av_idx; AVMediaType type; AVCodecID codec_id; + AVCodecContext *ctx; int64_t start_pts; int64_t end_pts; int64_t last_pts; int64_t duration; stream(AVMediaType ty, int i) { - type = ty; av_idx = i; + type = ty; av_idx = i; ctx = 0; start_pts = INT64_MAX; end_pts = INT64_MIN; last_pts = -1; } - ~stream() {} + ~stream() { if( ctx ) avcodec_free_context(&ctx); } }; class mark { @@ -1200,6 +1216,7 @@ public: ArrayList cl; ArrayList pl; + void add_movie(uint32_t *ops, int n); int compose(); int write(char *fn); @@ -1402,7 +1419,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 +1547,7 @@ clpi_prog_stream::write() return 1; }; + bs.padb(0x15 - bs_posb(bs)); bs_end(bs); return 0; } @@ -1734,6 +1752,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 +1813,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 +1925,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 +1969,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 +2333,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 +2370,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 +2398,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 +2407,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); @@ -2463,9 +2509,15 @@ static int field_probe(AVFormatContext *fmt_ctx, AVStream *st) { AVDictionary *copts = 0; //av_dict_copy(&copts, opts, 0); - AVCodecID codec_id = st->codec->codec_id; + AVCodecID codec_id = st->codecpar->codec_id; AVCodec *decoder = avcodec_find_decoder(codec_id); - if( avcodec_open2(st->codec, decoder, &copts) < 0 ) { + AVCodecContext *ctx = avcodec_alloc_context3(decoder); + if( !ctx ) { + fprintf(stderr,"codec alloc failed\n"); + return -1; + } + avcodec_parameters_to_context(ctx, st->codecpar); + if( avcodec_open2(ctx, decoder, &copts) < 0 ) { fprintf(stderr,"codec open failed\n"); return -1; } @@ -2480,22 +2532,24 @@ static int field_probe(AVFormatContext *fmt_ctx, AVStream *st) int ret = av_read_frame(fmt_ctx, &ipkt); if( ret == AVERROR_EOF ) break; if( ret != 0 ) continue; - if( !ipkt.data ) continue; if( ipkt.stream_index != st->index ) continue; - while( ipkt.size > 0 ) { - int got_frame = 0; - ret = avcodec_decode_video2(st->codec, ipic, &got_frame, &ipkt); - if( ret <= 0 ) break; - if( got_frame ) { - ilaced = ipic->interlaced_frame ? 1 : 0; - break; - } - ipkt.data += ret; - ipkt.size -= ret; + if( !ipkt.data || !ipkt.size ) continue; + ret = avcodec_send_packet(ctx, &ipkt); + if( ret < 0 ) { + fprintf(stderr, "avcodec_send_packet failed\n"); + break; + } + ret = avcodec_receive_frame(ctx, ipic); + if( ret >= 0 ) { + ilaced = ipic->interlaced_frame ? 1 : 0; + break; } + if( ret != AVERROR(EAGAIN) ) + fprintf(stderr, "avcodec_receive_frame failed %d\n", ret); } av_packet_unref(&ipkt); av_frame_free(&ipic); + avcodec_free_context(&ctx); return ilaced; } @@ -2520,15 +2574,22 @@ int media_info::scan() int ep_pid = -1; for( int i=0; ret>=0 && i<(int)fmt_ctx->nb_streams; ++i ) { AVStream *st = fmt_ctx->streams[i]; - AVMediaType type = st->codec->codec_type; + AVMediaType type = st->codecpar->codec_type; 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); s->pid = st->id; - AVCodecID codec_id = st->codec->codec_id; + AVCodecID codec_id = st->codecpar->codec_id; + AVCodec *decoder = avcodec_find_decoder(codec_id); + s->ctx = avcodec_alloc_context3(decoder); + if( !s->ctx ) { + fprintf(stderr, "avcodec_alloc_context failed\n"); + continue; + } switch( type ) { case AVMEDIA_TYPE_VIDEO: { if( ep_pid < 0 ) ep_pid = st->id; @@ -2538,18 +2599,23 @@ int media_info::scan() fprintf(stderr, "interlace probe failed\n"); exit(1); } - s->format = bd_video_format(st->codec->width, st->codec->height, ilace); - s->rate = bd_video_rate(!st->codec->framerate.den ? 0 : - (double)st->codec->framerate.num / st->codec->framerate.den); - s->aspect = bd_aspect_ratio(st->codec->width, st->codec->height, + s->format = bd_video_format(st->codecpar->width, st->codecpar->height, ilace); + AVRational framerate = av_guess_frame_rate(fmt_ctx, st, 0); + s->rate = bd_video_rate(!framerate.den ? 0 : (double)framerate.num / framerate.den); + s->aspect = bd_aspect_ratio(st->codecpar->width, st->codecpar->height, !st->sample_aspect_ratio.num || !st->sample_aspect_ratio.den ? 1. : (double)st->sample_aspect_ratio.num / st->sample_aspect_ratio.den); break; } case AVMEDIA_TYPE_AUDIO: { 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"); + s->format = bd_audio_format(st->codecpar->channels); + s->rate = bd_audio_rate(st->codecpar->sample_rate); + 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; @@ -2562,9 +2628,8 @@ int media_info::scan() s->duration = av_rescale_q(st->duration, st->time_base, clk45k); streams.append(s); - AVCodec *decoder = avcodec_find_decoder(codec_id); AVDictionary *copts = 0; - ret = avcodec_open2(st->codec, decoder, &copts); + ret = avcodec_open2(s->ctx, decoder, &copts); } if( ep_pid < 0 ) ep_pid = fmt_ctx->nb_streams > 0 ? fmt_ctx->streams[0]->id : 0; @@ -2574,11 +2639,11 @@ 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; jjstreams[jj]; - AVMediaType type = st->codec->codec_type; + AVMediaType type = st->codecpar->codec_type; switch( type ) { case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_AUDIO: @@ -2587,7 +2652,7 @@ int media_info::scan() continue; } pgm->strm_idx.append(jj); - if( pgm->duration < st->duration ) + if( !pgm->duration || st->duration < pgm->duration ) pgm->duration = av_rescale_q(st->duration, st->time_base, clk45k); } programs.append(pgm); @@ -2603,12 +2668,13 @@ int media_info::scan() for( int jj=0; jj<(int)pgrm->nb_stream_indexes; ++jj ) { int av_idx = pgrm->stream_index[jj]; AVStream *st = fmt_ctx->streams[av_idx]; - AVMediaType type = st->codec->codec_type; + AVMediaType type = st->codecpar->codec_type; switch( type ) { case AVMEDIA_TYPE_VIDEO: if( ep_pid < 0 ) ep_pid = st->id; break; case AVMEDIA_TYPE_AUDIO: + case AVMEDIA_TYPE_SUBTITLE: break; default: continue; @@ -2619,7 +2685,7 @@ int media_info::scan() fprintf(stderr, "bad stream idx %d in pgm %d\n",av_idx, ii); continue; } - if( pgm->duration < st->duration ) + if( !pgm->duration || st->duration < pgm->duration ) pgm->duration = av_rescale_q(st->duration, st->time_base, clk45k); pgm->strm_idx.append(sidx); } @@ -2635,8 +2701,8 @@ int media_info::scan() if( ret >= 0 ) ret = scan(fmt_ctx); - for( int i=0; i<(int)fmt_ctx->nb_streams; ++i ) - avcodec_close(fmt_ctx->streams[i]->codec); + for( int i=0; i<(int)streams.size(); ++i ) + avcodec_close(streams[i]->ctx); avformat_close_input(&fmt_ctx); return ret; @@ -2647,7 +2713,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; iresume_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; iiresume_intention_flag = 1; @@ -2745,15 +2820,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 +2855,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 +2880,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 +2889,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 +2924,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 +2939,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 +2956,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 +2967,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; @@ -3052,7 +3139,6 @@ main(int ac, char **av) { char *path = av[1]; if( mkbdmv(path) ) return 1; - av_register_all(); av_log_set_level(AV_LOG_FATAL); //av_log_set_level(AV_LOG_VERBOSE); //av_log_set_level(AV_LOG_DEBUG);