summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2018-06-13 15:07:25 -0700
committerJohn Stebbins <[email protected]>2018-06-13 15:07:25 -0700
commitf1714ec672382862b10b3df7e81a0cb0bcaf34af (patch)
tree70c004bd6cea04aad0b248c27b204a0554e5d6fa /libhb
parentc85294a8f0bce69d5cb417f60a143663fb83772a (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.c13
-rw-r--r--libhb/common.c30
-rw-r--r--libhb/common.h95
-rw-r--r--libhb/decavcodec.c10
-rw-r--r--libhb/decpgssub.c22
-rw-r--r--libhb/dvd.c7
-rw-r--r--libhb/dvdnav.c7
-rw-r--r--libhb/stream.c60
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 );
}