diff options
author | Rodeo <[email protected]> | 2014-01-07 11:42:39 +0000 |
---|---|---|
committer | Rodeo <[email protected]> | 2014-01-07 11:42:39 +0000 |
commit | 7f46a78ce98fe1e1bf69cc431c3303eedc1f7f66 (patch) | |
tree | 5f2912aa05d9600d3655b9ed83a695e43725f659 /libhb/decavcodec.c | |
parent | 5bf5ef4f102648396941e4a1d1ce4af36638d16b (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.c | 278 |
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) { |