summaryrefslogtreecommitdiffstats
path: root/libhb/decavcodec.c
diff options
context:
space:
mode:
authorRodeo <[email protected]>2014-01-07 11:42:39 +0000
committerRodeo <[email protected]>2014-01-07 11:42:39 +0000
commit7f46a78ce98fe1e1bf69cc431c3303eedc1f7f66 (patch)
tree5f2912aa05d9600d3655b9ed83a695e43725f659 /libhb/decavcodec.c
parent5bf5ef4f102648396941e4a1d1ce4af36638d16b (diff)
Revert previous borked commit. Sorry!
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5958 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/decavcodec.c')
-rw-r--r--libhb/decavcodec.c278
1 files changed, 61 insertions, 217 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index f3d9c78cd..8f88267b5 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -86,7 +86,6 @@ struct hb_work_private_s
hb_title_t *title;
AVCodecContext *context;
AVCodecParserContext *parser;
- AVFrame *frame;
int threads;
int video_codec_opened;
hb_list_t *list;
@@ -130,8 +129,6 @@ struct hb_work_private_s
#endif
} qsv;
#endif
-
- hb_list_t * list_subtitle;
};
#ifdef USE_QSV_PTS_WORKAROUND
@@ -311,6 +308,7 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
{
// libavcodec can't decode TrueHD Mono (bug #356)
// work around it by requesting Stereo and downmixing
+ pv->context->request_channels = 2;
pv->context->request_channel_layout = AV_CH_LAYOUT_STEREO;
break;
}
@@ -329,24 +327,11 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
}
}
- // Set decoder opts...
- AVDictionary * av_opts = NULL;
- av_dict_set( &av_opts, "refcounted_frames", "1", 0 );
-
- if (hb_avcodec_open(pv->context, codec, &av_opts, 0))
+ if (hb_avcodec_open(pv->context, codec, NULL, 0))
{
- av_dict_free( &av_opts );
hb_log("decavcodecaInit: avcodec_open failed");
return 1;
}
- av_dict_free( &av_opts );
-
- pv->frame = av_frame_alloc();
- if (pv->frame == NULL)
- {
- hb_log("decavcodecaInit: av_frame_alloc failed");
- return 1;
- }
return 0;
}
@@ -372,7 +357,6 @@ static void closePrivData( hb_work_private_t ** ppv )
pv->context->codec->name, pv->nframes, pv->decode_errors,
pv->ndrops );
}
- av_frame_free(&pv->frame);
if ( pv->sws_context )
{
sws_freeContext( pv->sws_context );
@@ -421,7 +405,7 @@ static void closePrivData( hb_work_private_t ** ppv )
HB_OCL_BUF_FREE(hb_ocl, pv->dxva2->cl_mem_nv12);
}
hb_va_close(pv->dxva2);
- }
+ }
#endif
#ifdef USE_QSV_PTS_WORKAROUND
@@ -446,7 +430,7 @@ static void closePrivData( hb_work_private_t ** ppv )
static void decavcodecClose( hb_work_object_t * w )
{
hb_work_private_t * pv = w->private_data;
-#ifdef USE_HWD
+#ifdef USE_HWD
if( pv->dst_frame ) free( pv->dst_frame );
#endif
if ( pv )
@@ -611,28 +595,30 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
context->channel_layout == AV_CH_LAYOUT_MONO)
{
truehd_mono = 1;
+ context->request_channels = 2;
context->request_channel_layout = AV_CH_LAYOUT_STEREO;
}
else
{
+ context->request_channels = 0;
context->request_channel_layout = 0;
}
if (pbuffer_size > 0)
{
int got_frame;
- AVFrame *frame = av_frame_alloc();
+ AVFrame frame = { { 0 } };
AVPacket avp;
av_init_packet(&avp);
avp.data = pbuffer;
avp.size = pbuffer_size;
- len = avcodec_decode_audio4(context, frame, &got_frame, &avp);
+ len = avcodec_decode_audio4(context, &frame, &got_frame, &avp);
if (len > 0 && context->sample_rate > 0)
{
info->rate_base = 1;
info->rate = context->sample_rate;
- info->samples_per_frame = frame->nb_samples;
+ info->samples_per_frame = frame.nb_samples;
int bps = av_get_bits_per_sample(context->codec_id);
if (bps > 0 && context->channels > 0)
@@ -706,7 +692,7 @@ static uint8_t *copy_plane( uint8_t *dst, uint8_t* src, int dstride, int sstride
// copy one video frame into an HB buf. If the frame isn't in our color space
// or at least one of its dimensions is odd, use sws_scale to convert/rescale it.
// Otherwise just copy the bits.
-static hb_buffer_t *copy_frame( hb_work_private_t *pv )
+static hb_buffer_t *copy_frame( hb_work_private_t *pv, AVFrame *frame )
{
AVCodecContext *context = pv->context;
int w, h;
@@ -738,7 +724,7 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv )
{
pv->dst_frame = malloc( ww * hh * 3 / 2 );
}
- if( hb_va_extract( pv->dxva2, pv->dst_frame, pv->frame, pv->job->width, pv->job->height, pv->job->title->crop, pv->opencl_scale, pv->job->use_opencl, pv->job->use_decomb, pv->job->use_detelecine ) == HB_WORK_ERROR )
+ if( hb_va_extract( pv->dxva2, pv->dst_frame, frame, pv->job->width, pv->job->height, pv->job->title->crop, pv->opencl_scale, pv->job->use_opencl, pv->job->use_decomb, pv->job->use_detelecine ) == HB_WORK_ERROR )
{
hb_log( "hb_va_Extract failed!!!!!!" );
}
@@ -766,7 +752,7 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv )
if (pv->qsv.decode &&
pv->qsv.config.io_pattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY)
{
- buf->qsv_details.qsv_atom = pv->frame->data[2];
+ buf->qsv_details.qsv_atom = frame->data[2];
return buf;
}
#endif
@@ -797,8 +783,7 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv )
pv->sws_pix_fmt = context->pix_fmt;
}
sws_scale(pv->sws_context,
- (const uint8_t* const *)pv->frame->data,
- pv->frame->linesize,
+ (const uint8_t* const *)frame->data, frame->linesize,
0, context->height, dstpic.data, dstpic.linesize);
}
else
@@ -806,15 +791,15 @@ static hb_buffer_t *copy_frame( hb_work_private_t *pv )
w = buf->plane[0].stride;
h = buf->plane[0].height;
dst = buf->plane[0].data;
- copy_plane( dst, pv->frame->data[0], w, pv->frame->linesize[0], h );
+ copy_plane( dst, frame->data[0], w, frame->linesize[0], h );
w = buf->plane[1].stride;
h = buf->plane[1].height;
dst = buf->plane[1].data;
- copy_plane( dst, pv->frame->data[1], w, pv->frame->linesize[1], h );
+ copy_plane( dst, frame->data[1], w, frame->linesize[1], h );
w = buf->plane[2].stride;
h = buf->plane[2].height;
dst = buf->plane[2].data;
- copy_plane( dst, pv->frame->data[2], w, pv->frame->linesize[2], h );
+ copy_plane( dst, frame->data[2], w, frame->linesize[2], h );
}
return buf;
}
@@ -971,67 +956,6 @@ static void checkCadence( int * cadence, uint16_t flags, int64_t start )
hb_log("%fs: Film -> Video", (float)start / 90000);
}
-// send cc_buf to the CC decoder(s)
-static void cc_send_to_decoder(hb_work_private_t *pv, hb_buffer_t *buf)
-{
- if (buf == NULL)
- return;
-
- // if there's more than one decoder for the captions send a copy
- // of the buffer to all.
- hb_subtitle_t *subtitle;
- int ii = 0, n = hb_list_count(pv->list_subtitle);
- while (--n > 0)
- {
- // make a copy of the buf then forward it to the decoder
- hb_buffer_t *cpy = hb_buffer_dup(buf);
-
- subtitle = hb_list_item(pv->list_subtitle, ii++);
- hb_fifo_push(subtitle->fifo_in, cpy);
- }
- subtitle = hb_list_item(pv->list_subtitle, ii);
- hb_fifo_push( subtitle->fifo_in, buf );
-}
-
-static hb_buffer_t * cc_fill_buffer(hb_work_private_t *pv, uint8_t *cc, int size, int64_t pts)
-{
- int cc_count[4] = {0,};
- int ii;
- hb_buffer_t *buf = NULL;
-
- for (ii = 0; ii < size; ii += 3)
- {
- if ((cc[ii] & 0x04) == 0) // not valid
- continue;
- if ((cc[ii+1] & 0x7f) == 0 && (cc[ii+2] & 0x7f) == 0) // stuffing
- continue;
- int type = cc[ii] & 0x03;
- cc_count[type]++;
- }
-
- // Only handles CC1 for now.
- if (cc_count[0] > 0)
- {
- buf = hb_buffer_init(cc_count[0] * 2);
- buf->s.start = pts;
- int jj = 0;
- for (ii = 0; ii < size; ii += 3)
- {
- if ((cc[ii] & 0x04) == 0) // not valid
- continue;
- if ((cc[ii+1] & 0x7f) == 0 && (cc[ii+2] & 0x7f) == 0) // stuffing
- continue;
- int type = cc[ii] & 0x03;
- if (type == 0)
- {
- buf->data[jj++] = cc[ii+1];
- buf->data[jj++] = cc[ii+2];
- }
- }
- }
- return buf;
-}
-
/*
* Decodes a video frame from the specified raw packet data
* ('data', 'size', 'sequence').
@@ -1050,6 +974,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
{
hb_work_private_t *pv = w->private_data;
int got_picture, oldlevel = 0;
+ AVFrame frame = { { 0 } };
AVPacket avp;
if ( global_verbosity_level <= 1 )
@@ -1066,7 +991,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
/*
* libav avcodec_decode_video2() needs AVPacket flagged with AV_PKT_FLAG_KEY
* for some codecs. For example, sequence of PNG in a mov container.
- */
+ */
if ( frametype & HB_FRAME_KEY )
{
avp.flags |= AV_PKT_FLAG_KEY;
@@ -1086,7 +1011,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
}
#endif
- if ( avcodec_decode_video2( pv->context, pv->frame, &got_picture, &avp ) < 0 )
+ if ( avcodec_decode_video2( pv->context, &frame, &got_picture, &avp ) < 0 )
{
++pv->decode_errors;
}
@@ -1104,7 +1029,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
if (pv->qsv.decode && got_picture)
{
// we got a decoded frame, restore the lowest available PTS
- pv->frame->pkt_pts = hb_av_pop_next_pts(pv->qsv.pts_list);
+ frame.pkt_pts = hb_av_pop_next_pts(pv->qsv.pts_list);
}
#endif
@@ -1112,6 +1037,22 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
{
av_log_set_level( oldlevel );
}
+ if( got_picture && pv->wait_for_keyframe > 0 )
+ {
+ // Libav is inconsistant about how it flags keyframes. For many
+ // codecs it simply sets frame.key_frame. But for others, it only
+ // sets frame.pict_type. And for yet others neither gets set at all
+ // (qtrle).
+ int key = frame.key_frame || (w->codec_param != AV_CODEC_ID_H264 &&
+ (frame.pict_type == 0 ||
+ frame.pict_type == AV_PICTURE_TYPE_I));
+ if( !key )
+ {
+ pv->wait_for_keyframe--;
+ return 0;
+ }
+ pv->wait_for_keyframe = 0;
+ }
if( got_picture )
{
uint16_t flags = 0;
@@ -1134,9 +1075,9 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
double pts;
double frame_dur = pv->duration;
- if ( pv->frame->repeat_pict )
+ if ( frame.repeat_pict )
{
- frame_dur += pv->frame->repeat_pict * pv->field_duration;
+ frame_dur += frame.repeat_pict * pv->field_duration;
}
#ifdef USE_HWD
if( pv->dxva2 && pv->dxva2->do_job == HB_WORK_OK )
@@ -1144,107 +1085,49 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
if( avp.pts>0 )
{
if( pv->dxva2->input_pts[0] != 0 && pv->dxva2->input_pts[1] == 0 )
- pv->frame->pkt_pts = pv->dxva2->input_pts[0];
+ frame.pkt_pts = pv->dxva2->input_pts[0];
else
- pv->frame->pkt_pts = pv->dxva2->input_pts[0]<pv->dxva2->input_pts[1] ? pv->dxva2->input_pts[0] : pv->dxva2->input_pts[1];
+ frame.pkt_pts = pv->dxva2->input_pts[0]<pv->dxva2->input_pts[1] ? pv->dxva2->input_pts[0] : pv->dxva2->input_pts[1];
}
}
#endif
// If there was no pts for this frame, assume constant frame rate
// video & estimate the next frame time from the last & duration.
- if (pv->frame->pkt_pts == AV_NOPTS_VALUE || hb_gui_use_hwd_flag == 1)
+ if (frame.pkt_pts == AV_NOPTS_VALUE || hb_gui_use_hwd_flag == 1)
{
pts = pv->pts_next;
}
else
{
- pts = pv->frame->pkt_pts;
+ pts = frame.pkt_pts;
}
pv->pts_next = pts + frame_dur;
- if ( pv->frame->top_field_first )
+ if ( frame.top_field_first )
{
flags |= PIC_FLAG_TOP_FIELD_FIRST;
}
- if ( !pv->frame->interlaced_frame )
+ if ( !frame.interlaced_frame )
{
flags |= PIC_FLAG_PROGRESSIVE_FRAME;
}
- if ( pv->frame->repeat_pict == 1 )
+ if ( frame.repeat_pict == 1 )
{
flags |= PIC_FLAG_REPEAT_FIRST_FIELD;
}
- if ( pv->frame->repeat_pict == 2 )
+ if ( frame.repeat_pict == 2 )
{
flags |= PIC_FLAG_REPEAT_FRAME;
}
- // Check for CC data
- AVFrameSideData *sd;
- sd = av_frame_get_side_data(pv->frame, AV_FRAME_DATA_A53_CC);
- if (sd != NULL)
- {
- if (!pv->job && pv->title && sd->size > 0)
- {
- hb_subtitle_t *subtitle;
- int i = 0;
-
- while ((subtitle = hb_list_item(pv->title->list_subtitle, i++)))
- {
- /*
- * Let's call them 608 subs for now even if they aren't,
- * since they are the only types we grok.
- */
- if (subtitle->source == CC608SUB)
- {
- break;
- }
- }
- if (subtitle == NULL)
- {
- subtitle = calloc(sizeof( hb_subtitle_t ), 1);
- subtitle->track = 0;
- subtitle->id = 0;
- subtitle->format = TEXTSUB;
- subtitle->source = CC608SUB;
- subtitle->config.dest = PASSTHRUSUB;
- subtitle->codec = WORK_DECCC608;
- subtitle->type = 5;
- snprintf(subtitle->lang, sizeof( subtitle->lang ),
- "Closed Captions");
- /*
- * The language of the subtitles will be the same as the
- * first audio track, i.e. the same as the video.
- */
- hb_audio_t *audio = hb_list_item(pv->title->list_audio, 0);
- if (audio != NULL)
- {
- snprintf(subtitle->iso639_2, sizeof(subtitle->iso639_2),
- "%s", audio->config.lang.iso639_2);
- } else {
- snprintf(subtitle->iso639_2, sizeof(subtitle->iso639_2),
- "und");
- }
- hb_list_add(pv->title->list_subtitle, subtitle);
- }
- }
- if (pv->list_subtitle != NULL && sd->size > 0)
- {
- hb_buffer_t *cc_buf;
- cc_buf = cc_fill_buffer(pv, sd->data, sd->size, pts);
- cc_send_to_decoder(pv, cc_buf);
- }
- }
-
hb_buffer_t *buf;
// if we're doing a scan or this content couldn't have been broken
// by Microsoft we don't worry about timestamp reordering
if ( ! pv->job || ! pv->brokenByMicrosoft )
{
- buf = copy_frame( pv );
- av_frame_unref(pv->frame);
+ buf = copy_frame( pv, &frame );
buf->s.start = pts;
buf->sequence = sequence;
@@ -1311,8 +1194,7 @@ static int decodeFrame( hb_work_object_t *w, uint8_t *data, int size, int sequen
}
// add the new frame to the delayq & push its timestamp on the heap
- buf = copy_frame( pv );
- av_frame_unref(pv->frame);
+ buf = copy_frame( pv, &frame );
buf->sequence = sequence;
/* Store picture flags for later use by filters */
buf->s.flags = flags;
@@ -1379,8 +1261,6 @@ static void decodeVideo( hb_work_object_t *w, uint8_t *data, int size, int seque
}
#endif
flushDelayQueue(pv);
- if (pv->list_subtitle != NULL)
- cc_send_to_decoder(pv, hb_buffer_init(0));
}
}
@@ -1511,18 +1391,11 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
}
#endif
- // Set encoder opts...
- AVDictionary * av_opts = NULL;
- av_dict_set( &av_opts, "refcounted_frames", "1", 0 );
-
- if ( hb_avcodec_open( pv->context, codec, &av_opts, pv->threads ) )
+ if ( hb_avcodec_open( pv->context, codec, NULL, pv->threads ) )
{
- av_dict_free( &av_opts );
hb_log( "decavcodecvInit: avcodec_open failed" );
return 1;
}
- av_dict_free( &av_opts );
-
pv->video_codec_opened = 1;
// avi, mkv and possibly mp4 containers can contain the M$ VFW packed
// b-frames abortion that messes up frame ordering and timestamps.
@@ -1540,35 +1413,6 @@ static int decavcodecvInit( hb_work_object_t * w, hb_job_t * job )
pv->context->err_recognition = AV_EF_CRCCHECK;
pv->context->error_concealment = FF_EC_GUESS_MVS|FF_EC_DEBLOCK;
}
-
- pv->frame = av_frame_alloc();
- if (pv->frame == NULL)
- {
- hb_log("decavcodecvInit: av_frame_alloc failed");
- return 1;
- }
-
- /*
- * If not scanning, then are we supposed to extract Closed Captions
- * and send them to the decoder?
- */
- if (job != NULL && hb_list_count(job->list_subtitle) > 0)
- {
- hb_subtitle_t *subtitle;
- int i = 0;
-
- while ((subtitle = hb_list_item(job->list_subtitle, i++)) != NULL)
- {
- if (subtitle->source == CC608SUB)
- {
- if (pv->list_subtitle == NULL)
- {
- pv->list_subtitle = hb_list_init();
- }
- hb_list_add(pv->list_subtitle, subtitle);
- }
- }
- }
return 0;
}
@@ -1728,18 +1572,13 @@ static int decavcodecvWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
}
#endif
- AVDictionary * av_opts = NULL;
- av_dict_set( &av_opts, "refcounted_frames", "1", 0 );
-
// disable threaded decoding for scan, can cause crashes
- if ( hb_avcodec_open( pv->context, codec, &av_opts, pv->threads ) )
+ if ( hb_avcodec_open( pv->context, codec, NULL, pv->threads ) )
{
- av_dict_free( &av_opts );
hb_log( "decavcodecvWork: avcodec_open failed" );
*buf_out = hb_buffer_init( 0 );;
return HB_WORK_DONE;
}
- av_dict_free( &av_opts );
pv->video_codec_opened = 1;
}
@@ -1814,6 +1653,12 @@ static void compute_frame_duration( hb_work_private_t *pv )
tb = &(st->time_base);
duration = (double)tb->num / (double)tb->den;
}
+ else if ( st->r_frame_rate.den * 64L > st->r_frame_rate.num &&
+ st->r_frame_rate.num > st->r_frame_rate.den * 8L )
+ {
+ tb = &(st->r_frame_rate);
+ duration = (double)tb->den / (double)tb->num;
+ }
}
if ( !duration &&
pv->context->time_base.num * max_fps > pv->context->time_base.den &&
@@ -2031,6 +1876,7 @@ static void decodeAudio(hb_audio_t *audio, hb_work_private_t *pv, uint8_t *data,
while (pos < size)
{
int got_frame;
+ AVFrame frame = { { 0 } };
AVPacket avp;
av_init_packet(&avp);
@@ -2039,7 +1885,7 @@ static void decodeAudio(hb_audio_t *audio, hb_work_private_t *pv, uint8_t *data,
avp.pts = pv->pts_next;
avp.dts = AV_NOPTS_VALUE;
- int len = avcodec_decode_audio4(context, pv->frame, &got_frame, &avp);
+ int len = avcodec_decode_audio4(context, &frame, &got_frame, &avp);
if ((len < 0) || (!got_frame && !(loop_limit--)))
{
return;
@@ -2069,7 +1915,7 @@ static void decodeAudio(hb_audio_t *audio, hb_work_private_t *pv, uint8_t *data,
if (got_frame)
{
hb_buffer_t *out;
- double duration = pv->frame->nb_samples * pv->duration;
+ double duration = frame.nb_samples * pv->duration;
double pts_next = pv->pts_next + duration;
if (audio->config.out.codec & HB_ACODEC_PASS_FLAG)
@@ -2090,13 +1936,11 @@ static void decodeAudio(hb_audio_t *audio, hb_work_private_t *pv, uint8_t *data,
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);
+ out = hb_audio_resample(pv->resample, frame.extended_data,
+ frame.nb_samples);
}
- av_frame_unref(pv->frame);
if (out != NULL)
{