diff options
author | John Stebbins <[email protected]> | 2018-06-13 15:07:25 -0700 |
---|---|---|
committer | John Stebbins <[email protected]> | 2018-06-13 15:07:25 -0700 |
commit | f1714ec672382862b10b3df7e81a0cb0bcaf34af (patch) | |
tree | 70c004bd6cea04aad0b248c27b204a0554e5d6fa /libhb | |
parent | c85294a8f0bce69d5cb417f60a143663fb83772a (diff) |
Fix PGS subtitle decoding...
...And add a timebase to every stream.
ffmpeg's subtitle decoder internally converts the packet pts to
AV_TIME_BASE units based on AVCodecContext.pkt_timebase. If
pkt_timebase is not set, the PGS subtitle decoder only returns
AV_NOPTS_VALUE for timestamps. So setting pkt_timebase in decpgssub.c
fixes PGS subtitle decoding.
Confusingly, the subtitle decoder does not convert the pts *back* to the
input timebase, but instead leaves them in AV_TIME_BASE units upon
returning a decoded subtitle.
To get a head start on fixing any other such issues that might arrise, I
have also set pkt_timebase in all other avcodec decoders.
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/bd.c | 13 | ||||
-rw-r--r-- | libhb/common.c | 30 | ||||
-rw-r--r-- | libhb/common.h | 95 | ||||
-rw-r--r-- | libhb/decavcodec.c | 10 | ||||
-rw-r--r-- | libhb/decpgssub.c | 22 | ||||
-rw-r--r-- | libhb/dvd.c | 7 | ||||
-rw-r--r-- | libhb/dvdnav.c | 7 | ||||
-rw-r--r-- | libhb/stream.c | 60 |
8 files changed, 147 insertions, 97 deletions
diff --git a/libhb/bd.c b/libhb/bd.c index 4517d2075..b8fc6fc0a 100644 --- a/libhb/bd.c +++ b/libhb/bd.c @@ -115,9 +115,11 @@ static void add_subtitle(int track, hb_list_t *list_subtitle, BLURAY_STREAM_INFO snprintf(subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "%s", lang->iso639_2); - subtitle->reg_desc = STR4_TO_UINT32("HDMV"); - subtitle->stream_type = bdsub->coding_type; - subtitle->codec = codec; + subtitle->reg_desc = STR4_TO_UINT32("HDMV"); + subtitle->stream_type = bdsub->coding_type; + subtitle->codec = codec; + subtitle->timebase.num = 1; + subtitle->timebase.den = 90000; hb_log( "bd: subtitle id=0x%x, lang=%s, 3cc=%s", subtitle->id, subtitle->lang, subtitle->iso639_2 ); @@ -202,7 +204,10 @@ static void add_audio(int track, hb_list_t *list_audio, BLURAY_STREAM_INFO *bdau hb_log("bd: audio id=0x%x, lang=%s (%s), 3cc=%s", audio->id, audio->config.lang.simple, codec_name, audio->config.lang.iso639_2); - audio->config.in.track = track; + audio->config.in.track = track; + audio->config.in.timebase.num = 1; + audio->config.in.timebase.den = 90000; + hb_list_add( list_audio, audio ); return; } diff --git a/libhb/common.c b/libhb/common.c index bb5de65fb..403741410 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -3604,21 +3604,23 @@ hb_title_t * hb_title_init( char * path, int index ) t = calloc( sizeof( hb_title_t ), 1 ); - t->index = index; - t->playlist = -1; - t->list_audio = hb_list_init(); - t->list_chapter = hb_list_init(); - t->list_subtitle = hb_list_init(); - t->list_attachment = hb_list_init(); - t->metadata = hb_metadata_init(); + t->index = index; + t->playlist = -1; + t->list_audio = hb_list_init(); + t->list_chapter = hb_list_init(); + t->list_subtitle = hb_list_init(); + t->list_attachment = hb_list_init(); + t->metadata = hb_metadata_init(); strncat(t->path, path, sizeof(t->path) - 1); // default to decoding mpeg2 - t->video_id = 0xE0; - t->video_codec = WORK_DECAVCODECV; - t->video_codec_param = AV_CODEC_ID_MPEG2VIDEO; - t->angle_count = 1; - t->geometry.par.num = 1; - t->geometry.par.den = 1; + t->video_id = 0xE0; + t->video_codec = WORK_DECAVCODECV; + t->video_codec_param = AV_CODEC_ID_MPEG2VIDEO; + t->video_timebase.num = 1; + t->video_timebase.den = 90000; + t->angle_count = 1; + t->geometry.par.num = 1; + t->geometry.par.den = 1; return t; } @@ -4809,6 +4811,8 @@ int hb_srt_add( const hb_job_t * job, subtitle->format = TEXTSUB; subtitle->source = SRTSUB; subtitle->codec = WORK_DECSRTSUB; + subtitle->timebase.num = 1; + subtitle->timebase.den = 90000; lang = lang_for_code2(lang_code); if (lang == NULL) diff --git a/libhb/common.h b/libhb/common.h index b1f457d05..a91d608c9 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -813,6 +813,7 @@ struct hb_audio_config_s PRIVATE int encoder_delay; /* Encoder delay in samples. * These samples should be dropped * when decoding */ + PRIVATE hb_rational_t timebase; } in; struct @@ -943,14 +944,15 @@ struct hb_subtitle_s #ifdef __LIBHB__ /* Internal data */ - PRIVATE uint32_t codec; /* Input "codec" */ - PRIVATE uint32_t reg_desc; /* registration descriptor of source */ - PRIVATE uint32_t stream_type; /* stream type from source stream */ - PRIVATE uint32_t substream_type;/* substream for multiplexed streams */ - - hb_fifo_t * fifo_in; /* SPU ES */ - hb_fifo_t * fifo_raw; /* Decoded SPU */ - hb_fifo_t * fifo_out; /* Correct Timestamps, ready to be muxed */ + uint32_t codec; /* Input "codec" */ + uint32_t reg_desc; /* registration descriptor of source */ + uint32_t stream_type; /* stream type from source stream */ + uint32_t substream_type; /* substream for multiplexed streams */ + hb_rational_t timebase; + + hb_fifo_t * fifo_in; /* SPU ES */ + hb_fifo_t * fifo_raw; /* Decoded SPU */ + hb_fifo_t * fifo_out; /* Correct Timestamps, ready to be muxed */ hb_mux_data_t * mux_data; #endif }; @@ -1000,51 +1002,52 @@ struct hb_metadata_s struct hb_title_s { enum { HB_DVD_TYPE, HB_BD_TYPE, HB_STREAM_TYPE, HB_FF_STREAM_TYPE } type; - uint32_t reg_desc; - char path[1024]; - char name[1024]; - int index; - int playlist; - int vts; - int ttn; - int cell_start; - int cell_end; - uint64_t block_start; - uint64_t block_end; - uint64_t block_count; - int angle_count; - void * opaque_priv; + uint32_t reg_desc; + char path[1024]; + char name[1024]; + int index; + int playlist; + int vts; + int ttn; + int cell_start; + int cell_end; + uint64_t block_start; + uint64_t block_end; + uint64_t block_count; + int angle_count; + void * opaque_priv; /* Visual-friendly duration */ - int hours; - int minutes; - int seconds; + int hours; + int minutes; + int seconds; /* Exact duration (in 1/90000s) */ - uint64_t duration; + uint64_t duration; - int preview_count; - int has_resolution_change; + int preview_count; + int has_resolution_change; enum { HB_ROTATION_0, HB_ROTATION_90, HB_ROTATION_180, HB_ROTATION_270 } rotation; - hb_geometry_t geometry; - hb_rational_t dar; // aspect ratio for the title's video - hb_rational_t container_dar; // aspect ratio from container (0 if none) - int color_prim; - int color_transfer; - int color_matrix; - hb_rational_t vrate; - int crop[4]; + hb_geometry_t geometry; + hb_rational_t dar; // aspect ratio for the title's video + hb_rational_t container_dar; // aspect ratio from container (0 if none) + int color_prim; + int color_transfer; + int color_matrix; + hb_rational_t vrate; + int crop[4]; enum {HB_DVD_DEMUXER, HB_TS_DEMUXER, HB_PS_DEMUXER, HB_NULL_DEMUXER} demuxer; - int detected_interlacing; - int pcr_pid; /* PCR PID for TS streams */ - int video_id; /* demuxer stream id for video */ - int video_codec; /* worker object id of video codec */ - uint32_t video_stream_type; /* stream type from source stream */ - int video_codec_param; /* codec specific config */ - char * video_codec_name; - int video_bitrate; - char * container_name; - int data_rate; + int detected_interlacing; + int pcr_pid; /* PCR PID for TS streams */ + int video_id; /* demuxer stream id for video */ + int video_codec; /* worker object id of video codec */ + uint32_t video_stream_type; /* stream type from source stream */ + int video_codec_param; /* codec specific config */ + char * video_codec_name; + int video_bitrate; + hb_rational_t video_timebase; + char * container_name; + int data_rate; // additional supported video decoders (e.g. HW-accelerated implementations) int video_decode_support; diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index db677db1c..8daca6604 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -310,6 +310,9 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job ) hb_log("decavcodecaInit: avcodec_open failed"); return 1; } + pv->context->pkt_timebase.num = pv->audio->config.in.timebase.num; + pv->context->pkt_timebase.den = pv->audio->config.in.timebase.den; + // avcodec_open populates av_opts with the things it didn't recognize. AVDictionaryEntry *t = NULL; while ((t = av_dict_get(av_opts, "", t, AV_DICT_IGNORE_SUFFIX)) != NULL) @@ -657,6 +660,9 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf, av_dict_free( &av_opts ); return -1; } + context->pkt_timebase.num = audio->config.in.timebase.num; + context->pkt_timebase.den = audio->config.in.timebase.den; + av_dict_free( &av_opts ); unsigned char *parse_buffer; int parse_pos, parse_buffer_size; @@ -1668,6 +1674,8 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job ) hb_log( "decavcodecvInit: avcodec_open failed" ); return 1; } + pv->context->pkt_timebase.num = pv->title->video_timebase.num; + pv->context->pkt_timebase.den = pv->title->video_timebase.den; av_dict_free( &av_opts ); pv->video_codec_opened = 1; @@ -1843,6 +1851,8 @@ static int decavcodecvWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_close( &in ); return HB_WORK_OK; } + pv->context->pkt_timebase.num = pv->title->video_timebase.num; + pv->context->pkt_timebase.den = pv->title->video_timebase.den; av_dict_free( &av_opts ); pv->video_codec_opened = 1; } diff --git a/libhb/decpgssub.c b/libhb/decpgssub.c index 8e6532532..716231d39 100644 --- a/libhb/decpgssub.c +++ b/libhb/decpgssub.c @@ -50,11 +50,13 @@ static int decsubInit( hb_work_object_t * w, hb_job_t * job ) hb_buffer_list_clear(&pv->list); hb_buffer_list_clear(&pv->list_pass); - pv->discard_subtitle = 1; - pv->seen_forced_sub = 0; - pv->last_pts = AV_NOPTS_VALUE; - pv->context = context; - pv->job = job; + pv->discard_subtitle = 1; + pv->seen_forced_sub = 0; + pv->last_pts = AV_NOPTS_VALUE; + pv->context = context; + context->pkt_timebase.num = w->subtitle->timebase.num; + context->pkt_timebase.den = w->subtitle->timebase.den; + pv->job = job; // Set decoder opts... AVDictionary * av_opts = NULL; @@ -195,15 +197,7 @@ static int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in, av_init_packet( &avp ); avp.data = in->data; avp.size = in->size; - // libav wants pkt pts in AV_TIME_BASE units - if (in->s.start != AV_NOPTS_VALUE) - { - avp.pts = av_rescale(in->s.start, AV_TIME_BASE, 90000); - } - else - { - avp.pts = AV_NOPTS_VALUE; - } + avp.pts = in->s.start; int has_subtitle = 0; diff --git a/libhb/dvd.c b/libhb/dvd.c index dee82eb3e..3fd567c04 100644 --- a/libhb/dvd.c +++ b/libhb/dvd.c @@ -204,6 +204,8 @@ static void add_subtitle( hb_list_t * list_subtitle, int position, subtitle->stream_type = 0xbd; subtitle->substream_type = 0x20 + position; subtitle->codec = WORK_DECVOBSUB; + subtitle->timebase.num = 1; + subtitle->timebase.den = 90000; memcpy(subtitle->palette, palette, 16 * sizeof(uint32_t)); subtitle->palette_set = 1; @@ -572,7 +574,10 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur audio->config.lang.simple, codec_name, audio->config.lang.iso639_2, lang_extension); - audio->config.in.track = i; + audio->config.in.track = i; + audio->config.in.timebase.num = 1; + audio->config.in.timebase.den = 90000; + hb_list_add( title->list_audio, audio ); } diff --git a/libhb/dvdnav.c b/libhb/dvdnav.c index b0e7239c8..adbbb34e7 100644 --- a/libhb/dvdnav.c +++ b/libhb/dvdnav.c @@ -348,6 +348,8 @@ static void add_subtitle( hb_list_t * list_subtitle, int position, subtitle->stream_type = 0xbd; subtitle->substream_type = 0x20 + position; subtitle->codec = WORK_DECVOBSUB; + subtitle->timebase.num = 1; + subtitle->timebase.den = 90000; memcpy(subtitle->palette, palette, 16 * sizeof(uint32_t)); subtitle->palette_set = 1; @@ -752,7 +754,10 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura audio->config.lang.simple, codec_name, audio->config.lang.iso639_2, lang_extension); - audio->config.in.track = i; + audio->config.in.track = i; + audio->config.in.timebase.num = 1; + audio->config.in.timebase.den = 90000; + hb_list_add( title->list_audio, audio ); } diff --git a/libhb/stream.c b/libhb/stream.c index b1f67cf16..df7ddc1b6 100644 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -1078,6 +1078,8 @@ hb_title_t * hb_stream_title_scan(hb_stream_t *stream, hb_title_t * title) title->video_id = get_id( &stream->pes.list[idx] ); title->video_codec = stream->pes.list[idx].codec; title->video_codec_param = stream->pes.list[idx].codec_param; + title->video_timebase.num = 1; + title->video_timebase.den = 90000; if (stream->hb_stream_type == transport) { @@ -1967,8 +1969,10 @@ static void pes_add_subtitle_to_title( hb_subtitle_t *subtitle = calloc( sizeof( hb_subtitle_t ), 1 ); iso639_lang_t * lang; - subtitle->track = idx; - subtitle->id = id; + subtitle->track = idx; + subtitle->id = id; + subtitle->timebase.num = 1; + subtitle->timebase.den = 90000; switch ( pes->codec ) { @@ -2087,6 +2091,8 @@ static void pes_add_audio_to_title( audio->config.in.codec = pes->codec; audio->config.in.codec_param = pes->codec_param; + audio->config.in.timebase.num = 1; + audio->config.in.timebase.den = 90000; set_audio_description(audio, lang_for_code(pes->lang_code)); @@ -5098,6 +5104,12 @@ static void add_ffmpeg_audio(hb_title_t *title, hb_stream_t *stream, int id) audio->config.in.bitrate = 0; audio->config.in.encoder_delay = codecpar->initial_padding; + // If we ever improve our pipeline to allow other time bases... + // audio->config.in.timebase.num = st->time_base.num; + // audio->config.in.timebase.den = st->time_base.den; + audio->config.in.timebase.num = 1; + audio->config.in.timebase.den = 90000; + // set the input codec and extradata for Passthru switch (codecpar->codec_id) { @@ -5302,6 +5314,11 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id hb_subtitle_t *subtitle = calloc( 1, sizeof(*subtitle) ); subtitle->id = id; + // If we ever improve our pipeline to allow other time bases... + // subtitle->timebase.num = st->time_base.num; + // subtitle->timebase.den = st->time_base.den; + subtitle->timebase.num = 1; + subtitle->timebase.den = 90000; switch ( codecpar->codec_id ) { @@ -5528,12 +5545,14 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title ) int i; for (i = 0; i < ic->nb_streams; ++i ) { - if ( ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && - !(ic->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) && - avcodec_find_decoder( ic->streams[i]->codecpar->codec_id ) && + AVStream * st = ic->streams[i]; + + if ( st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + !(st->disposition & AV_DISPOSITION_ATTACHED_PIC) && + avcodec_find_decoder( st->codecpar->codec_id ) && title->video_codec == 0 ) { - AVCodecParameters *codecpar = ic->streams[i]->codecpar; + AVCodecParameters *codecpar = st->codecpar; if ( codecpar->format != AV_PIX_FMT_YUV420P && !sws_isSupportedInput( codecpar->format ) ) { @@ -5542,17 +5561,17 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title ) } title->video_id = i; stream->ffmpeg_video_id = i; - if ( ic->streams[i]->sample_aspect_ratio.num && - ic->streams[i]->sample_aspect_ratio.den ) + if ( st->sample_aspect_ratio.num && + st->sample_aspect_ratio.den ) { - title->geometry.par.num = ic->streams[i]->sample_aspect_ratio.num; - title->geometry.par.den = ic->streams[i]->sample_aspect_ratio.den; + title->geometry.par.num = st->sample_aspect_ratio.num; + title->geometry.par.den = st->sample_aspect_ratio.den; } int j; - for (j = 0; j < ic->streams[i]->nb_side_data; j++) + for (j = 0; j < st->nb_side_data; j++) { - AVPacketSideData sd = ic->streams[i]->side_data[j]; + AVPacketSideData sd = st->side_data[j]; switch (sd.type) { case AV_PKT_DATA_DISPLAYMATRIX: @@ -5582,23 +5601,28 @@ static hb_title_t *ffmpeg_title_scan( hb_stream_t *stream, hb_title_t *title ) } } - title->video_codec = WORK_DECAVCODECV; - title->video_codec_param = codecpar->codec_id; + title->video_codec = WORK_DECAVCODECV; + title->video_codec_param = codecpar->codec_id; + // If we ever improve our pipeline to allow other time bases... + // title->video_timebase.num = st->time_base.num; + // title->video_timebase.den = st->time_base.den; + title->video_timebase.num = 1; + title->video_timebase.den = 90000; if (ic->iformat->raw_codec_id != AV_CODEC_ID_NONE) { title->flags |= HBTF_RAW_VIDEO; } } - else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && - avcodec_find_decoder( ic->streams[i]->codecpar->codec_id)) + else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + avcodec_find_decoder( st->codecpar->codec_id)) { add_ffmpeg_audio( title, stream, i ); } - else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) + else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { add_ffmpeg_subtitle( title, stream, i ); } - else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) + else if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) { add_ffmpeg_attachment( title, stream, i ); } |