1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Video Acceleration API (video encoding) encode sample 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 5cabdff1aSopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 6cabdff1aSopenharmony_ci * in the Software without restriction, including without limitation the rights 7cabdff1aSopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8cabdff1aSopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 9cabdff1aSopenharmony_ci * furnished to do so, subject to the following conditions: 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * The above copyright notice and this permission notice shall be included in 12cabdff1aSopenharmony_ci * all copies or substantial portions of the Software. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15cabdff1aSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16cabdff1aSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17cabdff1aSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18cabdff1aSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19cabdff1aSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20cabdff1aSopenharmony_ci * THE SOFTWARE. 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci/** 24cabdff1aSopenharmony_ci * @file 25cabdff1aSopenharmony_ci * Intel VAAPI-accelerated encoding example. 26cabdff1aSopenharmony_ci * 27cabdff1aSopenharmony_ci * @example vaapi_encode.c 28cabdff1aSopenharmony_ci * This example shows how to do VAAPI-accelerated encoding. now only support NV12 29cabdff1aSopenharmony_ci * raw file, usage like: vaapi_encode 1920 1080 input.yuv output.h264 30cabdff1aSopenharmony_ci * 31cabdff1aSopenharmony_ci */ 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci#include <stdio.h> 34cabdff1aSopenharmony_ci#include <string.h> 35cabdff1aSopenharmony_ci#include <errno.h> 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci#include <libavcodec/avcodec.h> 38cabdff1aSopenharmony_ci#include <libavutil/pixdesc.h> 39cabdff1aSopenharmony_ci#include <libavutil/hwcontext.h> 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_cistatic int width, height; 42cabdff1aSopenharmony_cistatic AVBufferRef *hw_device_ctx = NULL; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_cistatic int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx) 45cabdff1aSopenharmony_ci{ 46cabdff1aSopenharmony_ci AVBufferRef *hw_frames_ref; 47cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx = NULL; 48cabdff1aSopenharmony_ci int err = 0; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) { 51cabdff1aSopenharmony_ci fprintf(stderr, "Failed to create VAAPI frame context.\n"); 52cabdff1aSopenharmony_ci return -1; 53cabdff1aSopenharmony_ci } 54cabdff1aSopenharmony_ci frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data); 55cabdff1aSopenharmony_ci frames_ctx->format = AV_PIX_FMT_VAAPI; 56cabdff1aSopenharmony_ci frames_ctx->sw_format = AV_PIX_FMT_NV12; 57cabdff1aSopenharmony_ci frames_ctx->width = width; 58cabdff1aSopenharmony_ci frames_ctx->height = height; 59cabdff1aSopenharmony_ci frames_ctx->initial_pool_size = 20; 60cabdff1aSopenharmony_ci if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) { 61cabdff1aSopenharmony_ci fprintf(stderr, "Failed to initialize VAAPI frame context." 62cabdff1aSopenharmony_ci "Error code: %s\n",av_err2str(err)); 63cabdff1aSopenharmony_ci av_buffer_unref(&hw_frames_ref); 64cabdff1aSopenharmony_ci return err; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref); 67cabdff1aSopenharmony_ci if (!ctx->hw_frames_ctx) 68cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci av_buffer_unref(&hw_frames_ref); 71cabdff1aSopenharmony_ci return err; 72cabdff1aSopenharmony_ci} 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_cistatic int encode_write(AVCodecContext *avctx, AVFrame *frame, FILE *fout) 75cabdff1aSopenharmony_ci{ 76cabdff1aSopenharmony_ci int ret = 0; 77cabdff1aSopenharmony_ci AVPacket *enc_pkt; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci if (!(enc_pkt = av_packet_alloc())) 80cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci if ((ret = avcodec_send_frame(avctx, frame)) < 0) { 83cabdff1aSopenharmony_ci fprintf(stderr, "Error code: %s\n", av_err2str(ret)); 84cabdff1aSopenharmony_ci goto end; 85cabdff1aSopenharmony_ci } 86cabdff1aSopenharmony_ci while (1) { 87cabdff1aSopenharmony_ci ret = avcodec_receive_packet(avctx, enc_pkt); 88cabdff1aSopenharmony_ci if (ret) 89cabdff1aSopenharmony_ci break; 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci enc_pkt->stream_index = 0; 92cabdff1aSopenharmony_ci ret = fwrite(enc_pkt->data, enc_pkt->size, 1, fout); 93cabdff1aSopenharmony_ci av_packet_unref(enc_pkt); 94cabdff1aSopenharmony_ci } 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ciend: 97cabdff1aSopenharmony_ci av_packet_free(&enc_pkt); 98cabdff1aSopenharmony_ci ret = ((ret == AVERROR(EAGAIN)) ? 0 : -1); 99cabdff1aSopenharmony_ci return ret; 100cabdff1aSopenharmony_ci} 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ciint main(int argc, char *argv[]) 103cabdff1aSopenharmony_ci{ 104cabdff1aSopenharmony_ci int size, err; 105cabdff1aSopenharmony_ci FILE *fin = NULL, *fout = NULL; 106cabdff1aSopenharmony_ci AVFrame *sw_frame = NULL, *hw_frame = NULL; 107cabdff1aSopenharmony_ci AVCodecContext *avctx = NULL; 108cabdff1aSopenharmony_ci const AVCodec *codec = NULL; 109cabdff1aSopenharmony_ci const char *enc_name = "h264_vaapi"; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci if (argc < 5) { 112cabdff1aSopenharmony_ci fprintf(stderr, "Usage: %s <width> <height> <input file> <output file>\n", argv[0]); 113cabdff1aSopenharmony_ci return -1; 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci width = atoi(argv[1]); 117cabdff1aSopenharmony_ci height = atoi(argv[2]); 118cabdff1aSopenharmony_ci size = width * height; 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci if (!(fin = fopen(argv[3], "r"))) { 121cabdff1aSopenharmony_ci fprintf(stderr, "Fail to open input file : %s\n", strerror(errno)); 122cabdff1aSopenharmony_ci return -1; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci if (!(fout = fopen(argv[4], "w+b"))) { 125cabdff1aSopenharmony_ci fprintf(stderr, "Fail to open output file : %s\n", strerror(errno)); 126cabdff1aSopenharmony_ci err = -1; 127cabdff1aSopenharmony_ci goto close; 128cabdff1aSopenharmony_ci } 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, 131cabdff1aSopenharmony_ci NULL, NULL, 0); 132cabdff1aSopenharmony_ci if (err < 0) { 133cabdff1aSopenharmony_ci fprintf(stderr, "Failed to create a VAAPI device. Error code: %s\n", av_err2str(err)); 134cabdff1aSopenharmony_ci goto close; 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci if (!(codec = avcodec_find_encoder_by_name(enc_name))) { 138cabdff1aSopenharmony_ci fprintf(stderr, "Could not find encoder.\n"); 139cabdff1aSopenharmony_ci err = -1; 140cabdff1aSopenharmony_ci goto close; 141cabdff1aSopenharmony_ci } 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci if (!(avctx = avcodec_alloc_context3(codec))) { 144cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 145cabdff1aSopenharmony_ci goto close; 146cabdff1aSopenharmony_ci } 147cabdff1aSopenharmony_ci 148cabdff1aSopenharmony_ci avctx->width = width; 149cabdff1aSopenharmony_ci avctx->height = height; 150cabdff1aSopenharmony_ci avctx->time_base = (AVRational){1, 25}; 151cabdff1aSopenharmony_ci avctx->framerate = (AVRational){25, 1}; 152cabdff1aSopenharmony_ci avctx->sample_aspect_ratio = (AVRational){1, 1}; 153cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_VAAPI; 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci /* set hw_frames_ctx for encoder's AVCodecContext */ 156cabdff1aSopenharmony_ci if ((err = set_hwframe_ctx(avctx, hw_device_ctx)) < 0) { 157cabdff1aSopenharmony_ci fprintf(stderr, "Failed to set hwframe context.\n"); 158cabdff1aSopenharmony_ci goto close; 159cabdff1aSopenharmony_ci } 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci if ((err = avcodec_open2(avctx, codec, NULL)) < 0) { 162cabdff1aSopenharmony_ci fprintf(stderr, "Cannot open video encoder codec. Error code: %s\n", av_err2str(err)); 163cabdff1aSopenharmony_ci goto close; 164cabdff1aSopenharmony_ci } 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci while (1) { 167cabdff1aSopenharmony_ci if (!(sw_frame = av_frame_alloc())) { 168cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 169cabdff1aSopenharmony_ci goto close; 170cabdff1aSopenharmony_ci } 171cabdff1aSopenharmony_ci /* read data into software frame, and transfer them into hw frame */ 172cabdff1aSopenharmony_ci sw_frame->width = width; 173cabdff1aSopenharmony_ci sw_frame->height = height; 174cabdff1aSopenharmony_ci sw_frame->format = AV_PIX_FMT_NV12; 175cabdff1aSopenharmony_ci if ((err = av_frame_get_buffer(sw_frame, 0)) < 0) 176cabdff1aSopenharmony_ci goto close; 177cabdff1aSopenharmony_ci if ((err = fread((uint8_t*)(sw_frame->data[0]), size, 1, fin)) <= 0) 178cabdff1aSopenharmony_ci break; 179cabdff1aSopenharmony_ci if ((err = fread((uint8_t*)(sw_frame->data[1]), size/2, 1, fin)) <= 0) 180cabdff1aSopenharmony_ci break; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci if (!(hw_frame = av_frame_alloc())) { 183cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 184cabdff1aSopenharmony_ci goto close; 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci if ((err = av_hwframe_get_buffer(avctx->hw_frames_ctx, hw_frame, 0)) < 0) { 187cabdff1aSopenharmony_ci fprintf(stderr, "Error code: %s.\n", av_err2str(err)); 188cabdff1aSopenharmony_ci goto close; 189cabdff1aSopenharmony_ci } 190cabdff1aSopenharmony_ci if (!hw_frame->hw_frames_ctx) { 191cabdff1aSopenharmony_ci err = AVERROR(ENOMEM); 192cabdff1aSopenharmony_ci goto close; 193cabdff1aSopenharmony_ci } 194cabdff1aSopenharmony_ci if ((err = av_hwframe_transfer_data(hw_frame, sw_frame, 0)) < 0) { 195cabdff1aSopenharmony_ci fprintf(stderr, "Error while transferring frame data to surface." 196cabdff1aSopenharmony_ci "Error code: %s.\n", av_err2str(err)); 197cabdff1aSopenharmony_ci goto close; 198cabdff1aSopenharmony_ci } 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci if ((err = (encode_write(avctx, hw_frame, fout))) < 0) { 201cabdff1aSopenharmony_ci fprintf(stderr, "Failed to encode.\n"); 202cabdff1aSopenharmony_ci goto close; 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci av_frame_free(&hw_frame); 205cabdff1aSopenharmony_ci av_frame_free(&sw_frame); 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci /* flush encoder */ 209cabdff1aSopenharmony_ci err = encode_write(avctx, NULL, fout); 210cabdff1aSopenharmony_ci if (err == AVERROR_EOF) 211cabdff1aSopenharmony_ci err = 0; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ciclose: 214cabdff1aSopenharmony_ci if (fin) 215cabdff1aSopenharmony_ci fclose(fin); 216cabdff1aSopenharmony_ci if (fout) 217cabdff1aSopenharmony_ci fclose(fout); 218cabdff1aSopenharmony_ci av_frame_free(&sw_frame); 219cabdff1aSopenharmony_ci av_frame_free(&hw_frame); 220cabdff1aSopenharmony_ci avcodec_free_context(&avctx); 221cabdff1aSopenharmony_ci av_buffer_unref(&hw_device_ctx); 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci return err; 224cabdff1aSopenharmony_ci} 225