summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libhb/decavcodec.c386
1 files changed, 222 insertions, 164 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index 57d3bba3a..d17fd1575 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -169,7 +169,8 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
if (pv->title->opaque_priv != NULL)
{
AVFormatContext *ic = (AVFormatContext*)pv->title->opaque_priv;
- avcodec_copy_context(pv->context, ic->streams[w->audio->id]->codec);
+ avcodec_parameters_to_context(pv->context,
+ ic->streams[w->audio->id]->codecpar);
// libav's eac3 parser toggles the codec_id in the context as
// it reads eac3 data between AV_CODEC_ID_AC3 and AV_CODEC_ID_EAC3.
// It detects an AC3 sync pattern sometimes in ac3_sync() which
@@ -503,11 +504,78 @@ static int decavcodecaInfo( hb_work_object_t *w, hb_work_info_t *info )
return 0;
}
+static int parse_adts_extradata( hb_audio_t * audio, AVCodecContext * context,
+ AVPacket * pkt )
+{
+ const AVBitStreamFilter * bsf;
+ AVBSFContext * ctx = NULL;
+ int ret;
+
+ bsf = av_bsf_get_by_name("aac_adtstoasc");
+ ret = av_bsf_alloc(bsf, &ctx);
+ if (ret < 0)
+ {
+ hb_error("decavcodec: bitstream filter alloc failure");
+ return ret;
+ }
+ ctx->time_base_in.num = 1;
+ ctx->time_base_in.den = audio->config.out.samplerate;
+ avcodec_parameters_from_context(ctx->par_in, context);
+ ret = av_bsf_init(ctx);
+ if (ret < 0)
+ {
+ hb_error("decavcodec: bitstream filter init failure");
+ av_bsf_free(&ctx);
+ return ret;
+ }
+
+ ret = av_bsf_send_packet(ctx, pkt);
+ if (ret < 0)
+ {
+ hb_error("decavcodec: av_bsf_send_packet failure");
+ av_bsf_free(&ctx);
+ return ret;
+ }
+
+ ret = av_bsf_receive_packet(ctx, pkt);
+ av_bsf_free(&ctx);
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+ {
+ return 0;
+ }
+ else if (ret < 0)
+ {
+ if (ret != AVERROR_INVALIDDATA)
+ {
+ hb_error("decavcodec: av_bsf_receive_packet failure %x", -ret);
+ }
+ return ret;
+ }
+
+ if (audio->priv.config.extradata.length == 0)
+ {
+ const uint8_t * extradata;
+ int size;
+
+ extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
+ &size);
+ if (extradata != NULL && size > 0)
+ {
+ int len;
+ len = MIN(size, HB_CONFIG_MAX_SIZE);
+ memcpy(audio->priv.config.extradata.bytes, extradata, len);
+ audio->priv.config.extradata.length = len;
+ }
+ }
+
+ return 0;
+}
+
static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
hb_work_info_t *info )
{
hb_work_private_t *pv = w->private_data;
- int ret = 0;
+ int result = 0, done = 0;
hb_audio_t *audio = w->audio;
memset( info, 0, sizeof(*info) );
@@ -533,7 +601,8 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
if (w->title && w->title->opaque_priv != NULL)
{
AVFormatContext *ic = (AVFormatContext*)w->title->opaque_priv;
- avcodec_copy_context(context, ic->streams[audio->id]->codec);
+ avcodec_parameters_to_context(context,
+ ic->streams[audio->id]->codecpar);
// libav's eac3 parser toggles the codec_id in the context as
// it reads eac3 data between AV_CODEC_ID_AC3 and AV_CODEC_ID_EAC3.
// It detects an AC3 sync pattern sometimes in ac3_sync() which
@@ -559,14 +628,14 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
}
av_dict_free( &av_opts );
unsigned char *parse_buffer;
- int parse_pos, dec_pos, parse_buffer_size;
+ int parse_pos, parse_buffer_size;
- while (buf != NULL && !ret)
+ while (buf != NULL && !done)
{
parse_pos = 0;
- while (parse_pos < buf->size)
+ while (parse_pos < buf->size && !done)
{
- int parse_len, truehd_mono = 0;
+ int parse_len, truehd_mono = 0, ret;
if (parser != NULL)
{
@@ -581,6 +650,12 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
parse_len = parse_buffer_size = buf->size - parse_pos;
}
+ if (parse_buffer_size == 0)
+ {
+ parse_pos += parse_len;
+ continue;
+ }
+
// libavcodec can't decode TrueHD Mono (bug #356)
// work around it by requesting Stereo before decoding
if (context->codec_id == AV_CODEC_ID_TRUEHD &&
@@ -594,24 +669,27 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
context->request_channel_layout = 0;
}
- dec_pos = 0;
- while (dec_pos < parse_buffer_size)
+ AVPacket avp;
+ av_init_packet(&avp);
+ avp.data = parse_buffer;
+ avp.size = parse_buffer_size;
+
+ ret = avcodec_send_packet(context, &avp);
+ if (ret < 0 && ret != AVERROR_EOF)
{
- int dec_len;
- int got_frame;
- AVFrame *frame = av_frame_alloc();
- AVPacket avp;
- av_init_packet(&avp);
- avp.data = parse_buffer + dec_pos;
- avp.size = parse_buffer_size - dec_pos;
-
- dec_len = avcodec_decode_audio4(context, frame, &got_frame, &avp);
- if (dec_len < 0)
+ parse_pos += parse_len;
+ continue;
+ }
+
+ AVFrame *frame = NULL;
+ do
+ {
+ if (frame == NULL)
{
- av_frame_free(&frame);
- break;
+ frame = av_frame_alloc();
}
- if (dec_len > 0 && got_frame)
+ ret = avcodec_receive_frame(context, frame);
+ if (ret >= 0)
{
// libavcoded doesn't consistently set frame->sample_rate
if (frame->sample_rate != 0)
@@ -688,35 +766,16 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
// Parse ADTS AAC streams for AudioSpecificConfig.
// This data is required in order to write
// proper headers in MP4 and MKV files.
- AVBitStreamFilterContext* aac_adtstoasc;
- aac_adtstoasc = av_bitstream_filter_init("aac_adtstoasc");
- if (aac_adtstoasc)
- {
- int ret, size;
- uint8_t *data;
- ret = av_bitstream_filter_filter(aac_adtstoasc, context,
- NULL, &data, &size, avp.data, avp.size, 0);
- if (ret >= 0 &&
- context->extradata_size > 0 &&
- audio->priv.config.extradata.length == 0)
- {
- int len;
- len = MIN(context->extradata_size, HB_CONFIG_MAX_SIZE);
- memcpy(audio->priv.config.extradata.bytes,
- context->extradata, len);
- audio->priv.config.extradata.length = len;
- }
- av_bitstream_filter_close(aac_adtstoasc);
- }
+ parse_adts_extradata(audio, context, &avp);
}
- ret = 1;
- av_frame_free(&frame);
+ result = 1;
+ done = 1;
+ av_frame_unref(frame);
break;
}
- dec_pos += dec_len;
- av_frame_free(&frame);
- }
+ } while (ret >= 0);
+ av_frame_free(&frame);
parse_pos += parse_len;
}
buf = buf->next;
@@ -731,7 +790,7 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
hb_avcodec_close( context );
av_freep( &context->extradata );
av_freep( &context );
- return ret;
+ return result;
}
reordered_data_t *
@@ -811,9 +870,9 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv )
reordered_data_t * reordered = NULL;
hb_buffer_t * out = hb_video_buffer_init( w, h );
- if (pv->frame->pkt_pts != AV_NOPTS_VALUE)
+ if (pv->frame->pts != AV_NOPTS_VALUE)
{
- reordered = reordered_hash_rem(pv, pv->frame->pkt_pts);
+ reordered = reordered_hash_rem(pv, pv->frame->pts);
}
if (reordered != NULL)
{
@@ -998,7 +1057,7 @@ static int get_frame_type(int type)
static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
{
hb_work_private_t *pv = w->private_data;
- int got_picture, oldlevel = 0;
+ int got_picture = 0, oldlevel = 0, ret;
AVPacket avp;
reordered_data_t * reordered;
@@ -1025,7 +1084,7 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
}
reordered_hash_add(pv, reordered);
- // libav avcodec_decode_video2() needs AVPacket flagged with
+ // libav avcodec video decoder needs AVPacket flagged with
// AV_PKT_FLAG_KEY for some codecs. For example, sequence of
// PNG in a mov container.
if (packet_info->frametype & HB_FRAME_MASK_KEY)
@@ -1050,9 +1109,10 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
hb_buffer_close(&pv->palette);
}
- if (avcodec_decode_video2(pv->context, pv->frame, &got_picture, &avp) < 0)
+ ret = avcodec_send_packet(pv->context, &avp);
+ if (ret < 0 && ret != AVERROR_EOF)
{
- ++pv->decode_errors;
+ return 0;
}
av_free_packet(&avp);
@@ -1062,17 +1122,24 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
pv->job->qsv.ctx == NULL && pv->video_codec_opened > 0)
{
// this is quite late, but we can't be certain that the QSV context is
- // available until after we call avcodec_decode_video2() at least once
+ // available until after we call avcodec_send_packet() at least once
pv->job->qsv.ctx = pv->context->priv_data;
}
#endif
- if ( global_verbosity_level <= 1 )
- {
- av_log_set_level( oldlevel );
- }
- if (got_picture)
+ do
{
+ ret = avcodec_receive_frame(pv->context, pv->frame);
+ if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+ {
+ ++pv->decode_errors;
+ }
+ if (ret < 0)
+ {
+ break;
+ }
+ got_picture = 1;
+
uint16_t flags = 0;
// ffmpeg makes it hard to attach a pts to a frame. if the MPEG ES
@@ -1082,7 +1149,7 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
// intermediate packet of some frame which never has a pts). we hope
// that when parse returns the frame to us the pts we originally
// handed it will be in parser->pts. we put this pts into avp.pts so
- // that when avcodec_decode_video finally gets around to allocating an
+ // that when avcodec_receive_frame finally gets around to allocating an
// AVFrame to hold the decoded frame, avcodec_default_get_buffer can
// stuff that pts into the it. if all of these relays worked at this
// point frame.pts should hold the frame's pts from the original data
@@ -1200,6 +1267,11 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
hb_buffer_list_append(&pv->list, out);
++pv->nframes;
+ } while (ret >= 0);
+
+ if ( global_verbosity_level <= 1 )
+ {
+ av_log_set_level( oldlevel );
}
return got_picture;
@@ -1394,7 +1466,8 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
AVFormatContext *ic = (AVFormatContext*)pv->title->opaque_priv;
pv->context = avcodec_alloc_context3(codec);
- avcodec_copy_context( pv->context, ic->streams[pv->title->video_id]->codec);
+ avcodec_parameters_to_context(pv->context,
+ ic->streams[pv->title->video_id]->codecpar);
pv->context->workaround_bugs = FF_BUG_AUTODETECT;
pv->context->err_recognition = AV_EF_CRCCHECK;
pv->context->error_concealment = FF_EC_GUESS_MVS|FF_EC_DEBLOCK;
@@ -1869,132 +1942,117 @@ hb_work_object_t hb_decavcodecv =
static void decodeAudio(hb_work_private_t *pv, packet_info_t * packet_info)
{
AVCodecContext * context = pv->context;
- int loop_limit = 256;
- int pos = 0;
- int64_t pts = packet_info->pts;
+ AVPacket avp;
+ int ret;
- while (pos < packet_info->size)
- {
- int got_frame;
- AVPacket avp;
+ av_init_packet(&avp);
+ avp.data = packet_info->data;
+ avp.size = packet_info->size;
+ avp.pts = packet_info->pts;
+ avp.dts = AV_NOPTS_VALUE;
- av_init_packet(&avp);
- avp.data = packet_info->data + pos;
- avp.size = packet_info->size - pos;
- avp.pts = pts;
- avp.dts = AV_NOPTS_VALUE;
+ ret = avcodec_send_packet(context, &avp);
+ if (ret < 0 && ret != AVERROR_EOF)
+ {
+ return;
+ }
- int len = avcodec_decode_audio4(context, pv->frame, &got_frame, &avp);
- if (len < 0)
+ do
+ {
+ ret = avcodec_receive_frame(context, pv->frame);
+ if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
{
- if (pts != AV_NOPTS_VALUE)
- {
- // Update next_pts since subsequent packets may have no
- // pts and depend on next_pts being up to date
- pv->next_pts = pts + pv->duration;
- }
++pv->decode_errors;
}
- if ((len < 0) || (!got_frame && !(loop_limit--)))
+ if (ret < 0)
+ {
+ break;
+ }
+
+ hb_buffer_t * out;
+ int samplerate;
+
+ // libavcoded doesn't yet consistently set frame->sample_rate
+ if (pv->frame->sample_rate != 0)
{
- return;
+ samplerate = pv->frame->sample_rate;
}
else
{
- loop_limit = 256;
+ samplerate = context->sample_rate;
}
+ pv->duration = (90000. * pv->frame->nb_samples / samplerate);
- pos += len;
-
- if (got_frame)
+ if (pv->audio->config.out.codec & HB_ACODEC_PASS_FLAG)
{
- hb_buffer_t * out;
- int samplerate;
-
- // libavcoded doesn't yet consistently set frame->sample_rate
- if (pv->frame->sample_rate != 0)
+ // Note that even though we are doing passthru, we had to decode
+ // so that we know the stop time and the pts of the next audio
+ // packet.
+ out = hb_buffer_init(avp.size);
+ memcpy(out->data, avp.data, avp.size);
+ }
+ else
+ {
+ AVFrameSideData *side_data;
+ if ((side_data =
+ av_frame_get_side_data(pv->frame,
+ AV_FRAME_DATA_DOWNMIX_INFO)) != NULL)
{
- samplerate = pv->frame->sample_rate;
+ double surround_mix_level, center_mix_level;
+ AVDownmixInfo * downmix_info;
+
+ downmix_info = (AVDownmixInfo*)side_data->data;
+ if (pv->audio->config.out.mixdown == HB_AMIXDOWN_DOLBY ||
+ pv->audio->config.out.mixdown == HB_AMIXDOWN_DOLBYPLII)
+ {
+ surround_mix_level = downmix_info->surround_mix_level_ltrt;
+ center_mix_level = downmix_info->center_mix_level_ltrt;
+ }
+ else
+ {
+ surround_mix_level = downmix_info->surround_mix_level;
+ center_mix_level = downmix_info->center_mix_level;
+ }
+ hb_audio_resample_set_mix_levels(pv->resample,
+ surround_mix_level,
+ center_mix_level,
+ downmix_info->lfe_mix_level);
}
- else
+ hb_audio_resample_set_channel_layout(pv->resample,
+ pv->frame->channel_layout);
+ hb_audio_resample_set_sample_fmt(pv->resample,
+ pv->frame->format);
+ if (hb_audio_resample_update(pv->resample))
{
- samplerate = context->sample_rate;
+ hb_log("decavcodec: hb_audio_resample_update() failed");
+ av_frame_unref(pv->frame);
+ return;
}
- pv->duration = (90000. * pv->frame->nb_samples / samplerate);
+ out = hb_audio_resample(pv->resample, pv->frame->extended_data,
+ pv->frame->nb_samples);
+ }
- if (pv->audio->config.out.codec & HB_ACODEC_PASS_FLAG)
+ if (out != NULL)
+ {
+ out->s.scr_sequence = packet_info->scr_sequence;
+ out->s.start = pv->frame->pts;
+ out->s.duration = pv->duration;
+ if (out->s.start == AV_NOPTS_VALUE)
{
- // Note that even though we are doing passthru, we had to decode
- // so that we know the stop time and the pts of the next audio
- // packet.
- out = hb_buffer_init(avp.size);
- memcpy(out->data, avp.data, avp.size);
+ out->s.start = pv->next_pts;
}
else
{
- AVFrameSideData *side_data;
- if ((side_data =
- av_frame_get_side_data(pv->frame,
- AV_FRAME_DATA_DOWNMIX_INFO)) != NULL)
- {
- double surround_mix_level, center_mix_level;
- AVDownmixInfo * downmix_info;
-
- downmix_info = (AVDownmixInfo*)side_data->data;
- if (pv->audio->config.out.mixdown == HB_AMIXDOWN_DOLBY ||
- pv->audio->config.out.mixdown == HB_AMIXDOWN_DOLBYPLII)
- {
- surround_mix_level = downmix_info->surround_mix_level_ltrt;
- center_mix_level = downmix_info->center_mix_level_ltrt;
- }
- else
- {
- surround_mix_level = downmix_info->surround_mix_level;
- center_mix_level = downmix_info->center_mix_level;
- }
- hb_audio_resample_set_mix_levels(pv->resample,
- surround_mix_level,
- center_mix_level,
- downmix_info->lfe_mix_level);
- }
- hb_audio_resample_set_channel_layout(pv->resample,
- pv->frame->channel_layout);
- hb_audio_resample_set_sample_fmt(pv->resample,
- pv->frame->format);
- if (hb_audio_resample_update(pv->resample))
- {
- hb_log("decavcodec: hb_audio_resample_update() failed");
- av_frame_unref(pv->frame);
- return;
- }
- out = hb_audio_resample(pv->resample, pv->frame->extended_data,
- pv->frame->nb_samples);
+ pv->next_pts = out->s.start;
}
-
- if (out != NULL)
+ if (pv->next_pts != (int64_t)AV_NOPTS_VALUE)
{
- out->s.scr_sequence = packet_info->scr_sequence;
- out->s.start = pv->frame->pkt_pts;
- out->s.duration = pv->duration;
- if (out->s.start == AV_NOPTS_VALUE)
- {
- out->s.start = pv->next_pts;
- }
- else
- {
- pv->next_pts = out->s.start;
- }
- if (pv->next_pts != (int64_t)AV_NOPTS_VALUE)
- {
- pv->next_pts += pv->duration;
- out->s.stop = pv->next_pts;
- }
- hb_buffer_list_append(&pv->list, out);
-
- pts = AV_NOPTS_VALUE;
+ pv->next_pts += pv->duration;
+ out->s.stop = pv->next_pts;
}
- av_frame_unref(pv->frame);
- ++pv->nframes;
+ hb_buffer_list_append(&pv->list, out);
}
- }
+ av_frame_unref(pv->frame);
+ ++pv->nframes;
+ } while (ret >= 0);
}