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; }
/* messy code alarm */ void video_frame_init(struct video_frame *frame, enum video_format format, uint32_t width, uint32_t height) { size_t size; size_t offsets[MAX_AV_PLANES]; int alignment = base_get_alignment(); if (!frame) return; memset(frame, 0, sizeof(struct video_frame)); memset(offsets, 0, sizeof(offsets)); switch (format) { case VIDEO_FORMAT_NONE: return; case VIDEO_FORMAT_I420: size = width * height; ALIGN_SIZE(size, alignment); offsets[0] = size; size += (width/2) * (height/2); ALIGN_SIZE(size, alignment); offsets[1] = size; size += (width/2) * (height/2); ALIGN_SIZE(size, alignment); frame->data[0] = bmalloc(size); frame->data[1] = (uint8_t*)frame->data[0] + offsets[0]; frame->data[2] = (uint8_t*)frame->data[0] + offsets[1]; frame->linesize[0] = width; frame->linesize[1] = width/2; frame->linesize[2] = width/2; break; case VIDEO_FORMAT_NV12: size = width * height; ALIGN_SIZE(size, alignment); offsets[0] = size; size += (width/2) * (height/2) * 2; ALIGN_SIZE(size, alignment); frame->data[0] = bmalloc(size); frame->data[1] = (uint8_t*)frame->data[0] + offsets[0]; frame->linesize[0] = width; frame->linesize[1] = width; break; case VIDEO_FORMAT_YVYU: case VIDEO_FORMAT_YUY2: case VIDEO_FORMAT_UYVY: size = width * height * 2; ALIGN_SIZE(size, alignment); frame->data[0] = bmalloc(size); frame->linesize[0] = width*2; break; case VIDEO_FORMAT_RGBA: case VIDEO_FORMAT_BGRA: case VIDEO_FORMAT_BGRX: size = width * height * 4; ALIGN_SIZE(size, alignment); frame->data[0] = bmalloc(size); frame->linesize[0] = width*4; break; } }