diff options
author | Anton Khirnov <anton@khirnov.net> | 2013-11-02 22:06:36 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2013-11-23 11:55:43 +0100 |
commit | 07fd0a22192805d56c635eb294dc26b0a54ae325 (patch) | |
tree | 1ee9675c6b69f5cde5e44bbb31a9d5856894cbe0 /avconv.c | |
parent | d4df02131b5522a99a4e6035368484e809706ed5 (diff) | |
download | ffmpeg-07fd0a22192805d56c635eb294dc26b0a54ae325.tar.gz |
avconv: add infrastructure for using hwaccels
Diffstat (limited to 'avconv.c')
-rw-r--r-- | avconv.c | 73 |
1 files changed, 73 insertions, 0 deletions
@@ -198,6 +198,7 @@ static void avconv_cleanup(int ret) av_frame_free(&input_streams[i]->filter_frame); av_dict_free(&input_streams[i]->opts); av_freep(&input_streams[i]->filters); + av_freep(&input_streams[i]->hwaccel_device); av_freep(&input_streams[i]); } @@ -1165,6 +1166,13 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) return ret; } + if (ist->hwaccel_retrieve_data && decoded_frame->format == ist->hwaccel_pix_fmt) { + err = ist->hwaccel_retrieve_data(ist->st->codec, decoded_frame); + if (err < 0) + goto fail; + } + ist->hwaccel_retrieved_pix_fmt = decoded_frame->format; + decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts, decoded_frame->pkt_dts); pkt->size = 0; @@ -1212,6 +1220,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) break; } +fail: av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; @@ -1359,6 +1368,63 @@ static void print_sdp(void) av_freep(&avc); } +static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt) +{ + int i; + for (i = 0; hwaccels[i].name; i++) + if (hwaccels[i].pix_fmt == pix_fmt) + return &hwaccels[i]; + return NULL; +} + +static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) +{ + InputStream *ist = s->opaque; + const enum AVPixelFormat *p; + int ret; + + for (p = pix_fmts; *p != -1; p++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p); + const HWAccel *hwaccel; + + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + break; + + hwaccel = get_hwaccel(*p); + if (!hwaccel || + (ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) || + (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id)) + continue; + + ret = hwaccel->init(s); + if (ret < 0) { + if (ist->hwaccel_id == hwaccel->id) { + av_log(NULL, AV_LOG_FATAL, + "%s hwaccel requested for input stream #%d:%d, " + "but cannot be initialized.\n", hwaccel->name, + ist->file_index, ist->st->index); + exit_program(1); + } + continue; + } + ist->active_hwaccel_id = hwaccel->id; + ist->hwaccel_pix_fmt = *p; + break; + } + + return *p; +} + +static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags) +{ + InputStream *ist = s->opaque; + + if (ist->hwaccel_get_buffer && frame->format == ist->hwaccel_pix_fmt) + return ist->hwaccel_get_buffer(s, frame, flags); + + return avcodec_default_get_buffer2(s, frame, flags); +} + static int init_input_stream(int ist_index, char *error, int error_len) { int i, ret; @@ -1381,6 +1447,11 @@ static int init_input_stream(int ist_index, char *error, int error_len) } } + ist->st->codec->opaque = ist; + ist->st->codec->get_format = get_format; + ist->st->codec->get_buffer2 = get_buffer; + ist->st->codec->thread_safe_callbacks = 1; + av_opt_set_int(ist->st->codec, "refcounted_frames", 1, 0); if (!av_dict_get(ist->opts, "threads", NULL, 0)) @@ -2272,6 +2343,8 @@ static int transcode(void) ist = input_streams[i]; if (ist->decoding_needed) { avcodec_close(ist->st->codec); + if (ist->hwaccel_uninit) + ist->hwaccel_uninit(ist->st->codec); } } |