summaryrefslogtreecommitdiff
path: root/avconv.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2013-11-02 22:06:36 +0100
committerAnton Khirnov <anton@khirnov.net>2013-11-23 11:55:43 +0100
commit07fd0a22192805d56c635eb294dc26b0a54ae325 (patch)
tree1ee9675c6b69f5cde5e44bbb31a9d5856894cbe0 /avconv.c
parentd4df02131b5522a99a4e6035368484e809706ed5 (diff)
downloadffmpeg-07fd0a22192805d56c635eb294dc26b0a54ae325.tar.gz
avconv: add infrastructure for using hwaccels
Diffstat (limited to 'avconv.c')
-rw-r--r--avconv.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/avconv.c b/avconv.c
index 1e8c25eef2..b2d20dd38a 100644
--- a/avconv.c
+++ b/avconv.c
@@ -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);
}
}