static av_cold int cudaupload_init(AVFilterContext *ctx) { CudaUploadContext *s = ctx->priv; char buf[64] = { 0 }; snprintf(buf, sizeof(buf), "%d", s->device_idx); return av_hwdevice_ctx_create(&s->hwdevice, AV_HWDEVICE_TYPE_CUDA, buf, NULL, 0); }
static int dxva2_alloc(AVCodecContext *s) { InputStream *ist = s->opaque; int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; DXVA2Context *ctx; HANDLE device_handle; HRESULT hr; AVHWDeviceContext *device_ctx; AVDXVA2DeviceContext *device_hwctx; int ret; ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return AVERROR(ENOMEM); ist->hwaccel_ctx = ctx; ist->hwaccel_uninit = dxva2_uninit; ist->hwaccel_get_buffer = dxva2_get_buffer; ist->hwaccel_retrieve_data = dxva2_retrieve_data; ret = av_hwdevice_ctx_create(&ctx->hw_device_ctx, AV_HWDEVICE_TYPE_DXVA2, ist->hwaccel_device, NULL, 0); if (ret < 0) goto fail; device_ctx = (AVHWDeviceContext*)ctx->hw_device_ctx->data; device_hwctx = device_ctx->hwctx; hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, &device_handle); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to open a device handle\n"); goto fail; } hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service); IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n"); goto fail; } ctx->tmp_frame = av_frame_alloc(); if (!ctx->tmp_frame) goto fail; s->hwaccel_context = av_mallocz(sizeof(struct dxva_context)); if (!s->hwaccel_context) goto fail; return 0; fail: dxva2_uninit(s); return AVERROR(EINVAL); }
static int qsv_device_init(InputStream *ist) { int err; err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_QSV, ist->hwaccel_device, NULL, 0); if (err < 0) { av_log(NULL, AV_LOG_ERROR, "Error creating a QSV device\n"); return err; } return 0; }
static int hw_decoder_init(AVCodecContext *ctx, const enum AVHWDeviceType type) { int err = 0; if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type, NULL, NULL, 0)) < 0) { fprintf(stderr, "Failed to create specified HW device.\n"); return err; } ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx); return err; }
static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { QSVDevicePriv *priv; enum AVHWDeviceType child_device_type; AVHWDeviceContext *child_device; AVDictionaryEntry *e; mfxIMPL impl; int ret; priv = av_mallocz(sizeof(*priv)); if (!priv) return AVERROR(ENOMEM); ctx->user_opaque = priv; ctx->free = qsv_device_free; e = av_dict_get(opts, "child_device", NULL, 0); if (CONFIG_VAAPI) child_device_type = AV_HWDEVICE_TYPE_VAAPI; else if (CONFIG_DXVA2) child_device_type = AV_HWDEVICE_TYPE_DXVA2; else { av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n"); return AVERROR(ENOSYS); } ret = av_hwdevice_ctx_create(&priv->child_device_ctx, child_device_type, e ? e->value : NULL, NULL, 0); if (ret < 0) return ret; child_device = (AVHWDeviceContext*)priv->child_device_ctx->data; impl = choose_implementation(device); return qsv_device_derive_from_child(ctx, impl, child_device, 0); }
bool CDVDVideoCodecDRMPRIME::Open(CDVDStreamInfo& hints, CDVDCodecOptions& options) { const AVCodec* pCodec = FindDecoder(hints); if (!pCodec) { CLog::Log(LOGDEBUG, "CDVDVideoCodecDRMPRIME::%s - unable to find decoder for codec %d", __FUNCTION__, hints.codec); return false; } CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - using decoder %s", __FUNCTION__, pCodec->long_name ? pCodec->long_name : pCodec->name); m_pCodecContext = avcodec_alloc_context3(pCodec); if (!m_pCodecContext) return false; const AVCodecHWConfig* pConfig = FindHWConfig(pCodec); if (pConfig && (pConfig->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) && pConfig->device_type == AV_HWDEVICE_TYPE_DRM) { CWinSystemGbm* winSystem = dynamic_cast<CWinSystemGbm*>(CServiceBroker::GetWinSystem()); if (av_hwdevice_ctx_create(&m_pCodecContext->hw_device_ctx, AV_HWDEVICE_TYPE_DRM, winSystem->GetDevicePath().c_str(), nullptr, 0) < 0) { CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unable to create hwdevice context", __FUNCTION__); avcodec_free_context(&m_pCodecContext); return false; } } m_pCodecContext->pix_fmt = AV_PIX_FMT_DRM_PRIME; m_pCodecContext->get_format = GetFormat; m_pCodecContext->codec_tag = hints.codec_tag; m_pCodecContext->coded_width = hints.width; m_pCodecContext->coded_height = hints.height; m_pCodecContext->bits_per_coded_sample = hints.bitsperpixel; m_pCodecContext->time_base.num = 1; m_pCodecContext->time_base.den = DVD_TIME_BASE; if (hints.extradata && hints.extrasize > 0) { m_pCodecContext->extradata_size = hints.extrasize; m_pCodecContext->extradata = (uint8_t*)av_mallocz(hints.extrasize + AV_INPUT_BUFFER_PADDING_SIZE); memcpy(m_pCodecContext->extradata, hints.extradata, hints.extrasize); } if (avcodec_open2(m_pCodecContext, pCodec, nullptr) < 0) { CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unable to open codec", __FUNCTION__); avcodec_free_context(&m_pCodecContext); return false; } if (m_pCodecContext->pix_fmt != AV_PIX_FMT_DRM_PRIME) { CLog::Log(LOGNOTICE, "CDVDVideoCodecDRMPRIME::%s - unexpected pix fmt %s", __FUNCTION__, av_get_pix_fmt_name(m_pCodecContext->pix_fmt)); avcodec_free_context(&m_pCodecContext); return false; } const char* pixFmtName = av_get_pix_fmt_name(m_pCodecContext->pix_fmt); m_processInfo.SetVideoPixelFormat(pixFmtName ? pixFmtName : ""); m_processInfo.SetVideoDimensions(hints.width, hints.height); m_processInfo.SetVideoDeintMethod("none"); m_processInfo.SetVideoDAR(hints.aspect); if (pCodec->name) m_name = std::string("ff-") + pCodec->name; else m_name = "ffmpeg"; m_processInfo.SetVideoDecoderName(m_name, true); return true; }
int main(int argc, char **argv) { int ret = 0; AVPacket dec_pkt; AVCodec *enc_codec; if (argc != 4) { fprintf(stderr, "Usage: %s <input file> <encode codec> <output file>\n" "The output format is guessed according to the file extension.\n" "\n", argv[0]); return -1; } ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0); if (ret < 0) { fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(ret)); return -1; } if ((ret = open_input_file(argv[1])) < 0) goto end; if (!(enc_codec = avcodec_find_encoder_by_name(argv[2]))) { fprintf(stderr, "Could not find encoder '%s'\n", argv[2]); ret = -1; goto end; } if ((ret = (avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, argv[3]))) < 0) { fprintf(stderr, "Failed to deduce output format from file extension. Error code: " "%s\n", av_err2str(ret)); goto end; } if (!(encoder_ctx = avcodec_alloc_context3(enc_codec))) { ret = AVERROR(ENOMEM); goto end; } ret = avio_open(&ofmt_ctx->pb, argv[3], AVIO_FLAG_WRITE); if (ret < 0) { fprintf(stderr, "Cannot open output file. " "Error code: %s\n", av_err2str(ret)); goto end; } /* read all packets and only transcoding video */ while (ret >= 0) { if ((ret = av_read_frame(ifmt_ctx, &dec_pkt)) < 0) break; if (video_stream == dec_pkt.stream_index) ret = dec_enc(&dec_pkt, enc_codec); av_packet_unref(&dec_pkt); } /* flush decoder */ dec_pkt.data = NULL; dec_pkt.size = 0; ret = dec_enc(&dec_pkt, enc_codec); av_packet_unref(&dec_pkt); /* flush encoder */ ret = encode_write(NULL); /* write the trailer for output stream */ av_write_trailer(ofmt_ctx); end: avformat_close_input(&ifmt_ctx); avformat_close_input(&ofmt_ctx); avcodec_free_context(&decoder_ctx); avcodec_free_context(&encoder_ctx); av_buffer_unref(&hw_device_ctx); return ret; }
bool VideoEncoderFFmpegPrivate::open() { nb_encoded = 0LL; if (codec_name.isEmpty()) { // copy ctx from muxer by copyAVCodecContext AVCodec *codec = avcodec_find_encoder(avctx->codec_id); AV_ENSURE_OK(avcodec_open2(avctx, codec, &dict), false); return true; } AVCodec *codec = avcodec_find_encoder_by_name(codec_name.toUtf8().constData()); if (!codec) { const AVCodecDescriptor* cd = avcodec_descriptor_get_by_name(codec_name.toUtf8().constData()); if (cd) { codec = avcodec_find_encoder(cd->id); } } if (!codec) { qWarning() << "Can not find encoder for codec " << codec_name; return false; } if (avctx) { avcodec_free_context(&avctx); avctx = 0; } avctx = avcodec_alloc_context3(codec); avctx->width = width; // coded_width works, why? avctx->height = height; // reset format_used to user defined format. important to update default format if format is invalid format_used = VideoFormat::Format_Invalid; AVPixelFormat fffmt = (AVPixelFormat)format.pixelFormatFFmpeg(); if (codec->pix_fmts && format.isValid()) { for (int i = 0; codec->pix_fmts[i] != AVPixelFormat(-1); ++i) { if (fffmt == codec->pix_fmts[i]) { format_used = format.pixelFormat(); break; } } } //avctx->sample_aspect_ratio = AVPixelFormat hwfmt = AVPixelFormat(-1); if (av_pix_fmt_desc_get(codec->pix_fmts[0])->flags & AV_PIX_FMT_FLAG_HWACCEL) hwfmt = codec->pix_fmts[0]; bool use_hwctx = false; if (hwfmt != AVPixelFormat(-1)) { #ifdef HAVE_AVHWCTX const AVHWDeviceType dt = fromHWAName(codec_name.section(QChar('_'), -1).toUtf8().constData()); if (dt != AVHWDeviceType(-1)) { use_hwctx = true; avctx->pix_fmt = hwfmt; hw_device_ctx = NULL; AV_ENSURE(av_hwdevice_ctx_create(&hw_device_ctx, dt, hwdev.toLatin1().constData(), NULL, 0), false); avctx->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); if (!avctx->hw_frames_ctx) { qWarning("Failed to create hw frame context for '%s'", codec_name.toLatin1().constData()); return false; } // get sw formats const void *hwcfg = NULL; AVHWFramesConstraints *constraints = av_hwdevice_get_hwframe_constraints(hw_device_ctx, hwcfg); const AVPixelFormat* in_fmts = constraints->valid_sw_formats; AVPixelFormat sw_fmt = AVPixelFormat(-1); if (in_fmts) { sw_fmt = in_fmts[0]; while (*in_fmts != AVPixelFormat(-1)) { if (*in_fmts == fffmt) sw_fmt = *in_fmts; sw_fmts.append(*in_fmts); ++in_fmts; } } else { sw_fmt = QTAV_PIX_FMT_C(YUV420P); } av_hwframe_constraints_free(&constraints); format_used = VideoFormat::pixelFormatFromFFmpeg(sw_fmt); // encoder surface pool parameters AVHWFramesContext* hwfs = (AVHWFramesContext*)avctx->hw_frames_ctx->data; hwfs->format = hwfmt; // must the same as avctx->pix_fmt hwfs->sw_format = sw_fmt; // if it's not set, vaapi will choose the last valid_sw_formats, but that's wrong for vaGetImage/DeriveImage. nvenc always need sw_format // hw upload parameters. encoder's hwframes is just for parameter checking, will never be intialized, so we allocate an individual one. hwframes_ref = av_hwframe_ctx_alloc(hw_device_ctx); if (!hwframes_ref) { qWarning("Failed to create hw frame context for uploading '%s'", codec_name.toLatin1().constData()); } else { hwframes = (AVHWFramesContext*)hwframes_ref->data; hwframes->format = hwfmt; } } #endif //HAVE_AVHWCTX } if (!use_hwctx) { // no hw device (videotoolbox, wrong device name etc.), or old ffmpeg // TODO: check frame is hw frame if (hwfmt == AVPixelFormat(-1)) { // sw enc if (format_used == VideoFormat::Format_Invalid) {// requested format is not supported by sw enc if (codec->pix_fmts) { //pix_fmts[0] is always a sw format here qDebug("use first supported pixel format '%d' for sw encoder", codec->pix_fmts[0]); format_used = VideoFormat::pixelFormatFromFFmpeg((int)codec->pix_fmts[0]); } } } else { if (format_used == VideoFormat::Format_Invalid) { // requested format is not supported by hw enc qDebug("use first supported sw pixel format '%d' for hw encoder", codec->pix_fmts[1]); if (codec->pix_fmts && codec->pix_fmts[1] != AVPixelFormat(-1)) format_used = VideoFormat::pixelFormatFromFFmpeg(codec->pix_fmts[1]); } } if (format_used == VideoFormat::Format_Invalid) { qWarning("fallback to yuv420p"); format_used = VideoFormat::Format_YUV420P; } avctx->pix_fmt = (AVPixelFormat)VideoFormat::pixelFormatToFFmpeg(format_used); } if (frame_rate > 0) avctx->time_base = av_d2q(1.0/frame_rate, frame_rate*1001.0+2); else avctx->time_base = av_d2q(1.0/VideoEncoder::defaultFrameRate(), VideoEncoder::defaultFrameRate()*1001.0+2); qDebug("size: %dx%d tbc: %f=%d/%d", width, height, av_q2d(avctx->time_base), avctx->time_base.num, avctx->time_base.den); avctx->bit_rate = bit_rate; //AVDictionary *dict = 0; if(avctx->codec_id == QTAV_CODEC_ID(H264)) { avctx->gop_size = 10; //avctx->max_b_frames = 3;//h264 av_dict_set(&dict, "preset", "fast", 0); //x264 av_dict_set(&dict, "tune", "zerolatency", 0); //x264 //av_dict_set(&dict, "profile", "main", 0); // conflict with vaapi (int values) } if(avctx->codec_id == AV_CODEC_ID_HEVC){ av_dict_set(&dict, "preset", "ultrafast", 0); av_dict_set(&dict, "tune", "zero-latency", 0); } if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO) { av_dict_set(&dict, "strict", "-2", 0); // mpeg2 arbitrary fps } applyOptionsForContext(); AV_ENSURE_OK(avcodec_open2(avctx, codec, &dict), false); // from mpv ao_lavc const int buffer_size = qMax<int>(qMax<int>(width*height*6+200, FF_MIN_BUFFER_SIZE), sizeof(AVPicture));//?? buffer.resize(buffer_size); return true; }
static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path) { int ret; ret = av_hwdevice_ctx_create(&enc->vadevice_ref, AV_HWDEVICE_TYPE_VAAPI, path, NULL, 0); if (ret < 0) { warn("Failed to create VAAPI device context: %s", av_err2str(ret)); return false; } enc->vaframes_ref = av_hwframe_ctx_alloc(enc->vadevice_ref); if (!enc->vaframes_ref) { warn("Failed to alloc HW frames context"); return false; } AVHWFramesContext *frames_ctx = (AVHWFramesContext *)enc->vaframes_ref->data; frames_ctx->format = AV_PIX_FMT_VAAPI; frames_ctx->sw_format = AV_PIX_FMT_NV12; frames_ctx->width = enc->context->width; frames_ctx->height = enc->context->height; frames_ctx->initial_pool_size = 20; ret = av_hwframe_ctx_init(enc->vaframes_ref); if (ret < 0) { warn("Failed to init HW frames context: %s", av_err2str(ret)); return false; } /* 2. Create software frame and picture */ enc->vframe = av_frame_alloc(); if (!enc->vframe) { warn("Failed to allocate video frame"); return false; } enc->vframe->format = enc->context->pix_fmt; enc->vframe->width = enc->context->width; enc->vframe->height = enc->context->height; enc->vframe->colorspace = enc->context->colorspace; enc->vframe->color_range = enc->context->color_range; ret = av_frame_get_buffer(enc->vframe, base_get_alignment()); if (ret < 0) { warn("Failed to allocate vframe: %s", av_err2str(ret)); return false; } /* 3. set up codec */ enc->context->pix_fmt = AV_PIX_FMT_VAAPI; enc->context->hw_frames_ctx = av_buffer_ref(enc->vaframes_ref); ret = avcodec_open2(enc->context, enc->vaapi, NULL); if (ret < 0) { warn("Failed to open VAAPI codec: %s", av_err2str(ret)); return false; } enc->initialized = true; return true; }
static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { AVQSVDeviceContext *hwctx = ctx->hwctx; QSVDevicePriv *priv; enum AVHWDeviceType child_device_type; AVDictionaryEntry *e; mfxVersion ver = { { 3, 1 } }; mfxIMPL impl; mfxHDL handle; mfxHandleType handle_type; mfxStatus err; int ret; priv = av_mallocz(sizeof(*priv)); if (!priv) return AVERROR(ENOMEM); ctx->user_opaque = priv; ctx->free = qsv_device_free; e = av_dict_get(opts, "child_device", NULL, 0); if (CONFIG_VAAPI) child_device_type = AV_HWDEVICE_TYPE_VAAPI; else if (CONFIG_DXVA2) child_device_type = AV_HWDEVICE_TYPE_DXVA2; else { av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n"); return AVERROR(ENOSYS); } ret = av_hwdevice_ctx_create(&priv->child_device_ctx, child_device_type, e ? e->value : NULL, NULL, 0); if (ret < 0) return ret; { AVHWDeviceContext *child_device_ctx = (AVHWDeviceContext*)priv->child_device_ctx->data; #if CONFIG_VAAPI AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx; handle_type = MFX_HANDLE_VA_DISPLAY; handle = (mfxHDL)child_device_hwctx->display; #elif CONFIG_DXVA2 AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx; handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; handle = (mfxHDL)child_device_hwctx->devmgr; #endif } impl = choose_implementation(device); err = MFXInit(impl, &ver, &hwctx->session); if (err != MFX_ERR_NONE) { av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); return AVERROR_UNKNOWN; } err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle); if (err != MFX_ERR_NONE) return AVERROR_UNKNOWN; return 0; }