| @@ -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); | |||
| } | |||
| } | |||
| @@ -48,6 +48,18 @@ | |||
| #define VSYNC_CFR 1 | |||
| #define VSYNC_VFR 2 | |||
| enum HWAccelID { | |||
| HWACCEL_NONE = 0, | |||
| HWACCEL_AUTO, | |||
| }; | |||
| typedef struct HWAccel { | |||
| const char *name; | |||
| int (*init)(AVCodecContext *s); | |||
| enum HWAccelID id; | |||
| enum AVPixelFormat pix_fmt; | |||
| } HWAccel; | |||
| /* select an input stream for an output stream */ | |||
| typedef struct StreamMap { | |||
| int disabled; /* 1 is this mapping is disabled by a negative map */ | |||
| @@ -94,6 +106,10 @@ typedef struct OptionsContext { | |||
| int nb_ts_scale; | |||
| SpecifierOpt *dump_attachment; | |||
| int nb_dump_attachment; | |||
| SpecifierOpt *hwaccels; | |||
| int nb_hwaccels; | |||
| SpecifierOpt *hwaccel_devices; | |||
| int nb_hwaccel_devices; | |||
| /* output options */ | |||
| StreamMap *stream_maps; | |||
| @@ -230,6 +246,19 @@ typedef struct InputStream { | |||
| * currently video and audio only */ | |||
| InputFilter **filters; | |||
| int nb_filters; | |||
| /* hwaccel options */ | |||
| enum HWAccelID hwaccel_id; | |||
| char *hwaccel_device; | |||
| /* hwaccel context */ | |||
| enum HWAccelID active_hwaccel_id; | |||
| void *hwaccel_ctx; | |||
| void (*hwaccel_uninit)(AVCodecContext *s); | |||
| int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); | |||
| int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); | |||
| enum AVPixelFormat hwaccel_pix_fmt; | |||
| enum AVPixelFormat hwaccel_retrieved_pix_fmt; | |||
| } InputStream; | |||
| typedef struct InputFile { | |||
| @@ -355,6 +384,8 @@ extern const AVIOInterruptCB int_cb; | |||
| extern const OptionDef options[]; | |||
| extern const HWAccel hwaccels[]; | |||
| void reset_options(OptionsContext *o); | |||
| void show_usage(void); | |||
| @@ -433,7 +433,8 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, | |||
| ist->st->sample_aspect_ratio : | |||
| ist->st->codec->sample_aspect_ratio; | |||
| snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width, | |||
| ist->st->codec->height, ist->st->codec->pix_fmt, | |||
| ist->st->codec->height, | |||
| ist->hwaccel_retrieve_data ? ist->hwaccel_retrieved_pix_fmt : ist->st->codec->pix_fmt, | |||
| tb.num, tb.den, sar.num, sar.den); | |||
| snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, | |||
| ist->file_index, ist->st->index); | |||
| @@ -53,6 +53,10 @@ | |||
| }\ | |||
| } | |||
| const HWAccel hwaccels[] = { | |||
| { 0 }, | |||
| }; | |||
| char *vstats_filename; | |||
| float audio_drift_threshold = 0.1; | |||
| @@ -455,7 +459,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) | |||
| AVStream *st = ic->streams[i]; | |||
| AVCodecContext *dec = st->codec; | |||
| InputStream *ist = av_mallocz(sizeof(*ist)); | |||
| char *framerate = NULL; | |||
| char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL; | |||
| if (!ist) | |||
| exit_program(1); | |||
| @@ -488,6 +492,40 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) | |||
| exit_program(1); | |||
| } | |||
| MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); | |||
| if (hwaccel) { | |||
| if (!strcmp(hwaccel, "none")) | |||
| ist->hwaccel_id = HWACCEL_NONE; | |||
| else if (!strcmp(hwaccel, "auto")) | |||
| ist->hwaccel_id = HWACCEL_AUTO; | |||
| else { | |||
| int i; | |||
| for (i = 0; hwaccels[i].name; i++) { | |||
| if (!strcmp(hwaccels[i].name, hwaccel)) { | |||
| ist->hwaccel_id = hwaccels[i].id; | |||
| break; | |||
| } | |||
| } | |||
| if (!ist->hwaccel_id) { | |||
| av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", | |||
| hwaccel); | |||
| av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: "); | |||
| for (i = 0; hwaccels[i].name; i++) | |||
| av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name); | |||
| av_log(NULL, AV_LOG_FATAL, "\n"); | |||
| exit_program(1); | |||
| } | |||
| } | |||
| } | |||
| MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st); | |||
| if (hwaccel_device) { | |||
| ist->hwaccel_device = av_strdup(hwaccel_device); | |||
| if (!ist->hwaccel_device) | |||
| exit_program(1); | |||
| } | |||
| break; | |||
| case AVMEDIA_TYPE_AUDIO: | |||
| guess_input_channel_layout(ist); | |||
| @@ -2282,6 +2320,12 @@ const OptionDef options[] = { | |||
| { "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | | |||
| OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(forced_key_frames) }, | |||
| "force key frames at specified timestamps", "timestamps" }, | |||
| { "hwaccel", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | | |||
| OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccels) }, | |||
| "use HW accelerated decoding", "hwaccel name" }, | |||
| { "hwaccel_device", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | | |||
| OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_devices) }, | |||
| "select a device for HW acceleration" "devicename" }, | |||
| /* audio options */ | |||
| { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, | |||
| @@ -552,6 +552,33 @@ The timestamps must be specified in ascending order. | |||
| @item -copyinkf[:@var{stream_specifier}] (@emph{output,per-stream}) | |||
| When doing stream copy, copy also non-key frames found at the | |||
| beginning. | |||
| @item -hwaccel[:@var{stream_specifier}] @var{hwaccel} (@emph{input,per-stream}) | |||
| Use hardware acceleration to decode the matching stream(s). The allowed values | |||
| of @var{hwaccel} are: | |||
| @table @option | |||
| @item none | |||
| Do not use any hardware acceleration (the default). | |||
| @item auto | |||
| Automatically select the hardware acceleration method. | |||
| @end table | |||
| This option has no effect if the selected hwaccel is not available or not | |||
| supported by the chosen decoder. | |||
| Note that most acceleration methods are intended for playback and will not be | |||
| faster than software decoding on modern CPUs. Additionally, @command{avconv} | |||
| will usually need to copy the decoded frames from the GPU memory into the system | |||
| memory, resulting in further performance loss. This option is thus mainly | |||
| useful for testing. | |||
| @item -hwaccel_device[:@var{stream_specifier}] @var{hwaccel_device} (@emph{input,per-stream}) | |||
| Select a device to use for hardware acceleration. | |||
| This option only makes sense when the @option{-hwaccel} option is also | |||
| specified. Its exact meaning depends on the specific hardware acceleration | |||
| method chosen. | |||
| @end table | |||
| @section Audio Options | |||