static int encode2(AVFormatContext* fmtCtx, AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, FILE *outfile)
{
int ret = 0;
if (0 > avcodec_send_frame(enc_ctx, frame))
return -1;
while (true)
{
ret = avcodec_receive_packet(enc_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0)
return -1;
pkt->dts = pkt->pts;
ret = av_write_frame(fmtCtx, pkt);
av_packet_unref(pkt);
//fwrite(pkt->data, 1, pkt->size, outfile);
}
return 0;
}
bool yuv_to_h264_2(const char* szInput, const char* szOutput)
{
int ret = 0;
FILE* infile = nullptr, *outfile = nullptr;
AVCodecContext* pCodecCtx = avcodec_alloc_context3(nullptr);
AVFormatContext* pOutputFmtCtx = nullptr;
ret = avformat_alloc_output_context2(&pOutputFmtCtx, nullptr, nullptr, szOutput);
AVOutputFormat* pFmt = pOutputFmtCtx->oformat;
ret = avio_open2(&pOutputFmtCtx->pb, szOutput, AVIO_FLAG_READ_WRITE,nullptr,nullptr);
AVStream* pVideoStream = avformat_new_stream(pOutputFmtCtx, nullptr);
pVideoStream->time_base = { 1,25 };
avcodec_parameters_to_context(pCodecCtx, pVideoStream->codecpar);
// 設定編碼引數
pCodecCtx->codec_id = pFmt->video_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->width = 360;
pCodecCtx->height = 270;
pCodecCtx->time_base = { 1,25 };
pCodecCtx->framerate = { 25,1 };
pCodecCtx->gop_size = 250;
pCodecCtx->max_b_frames = 3;
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pCodecCtx->qmin = 10;
pCodecCtx->qmax = 51;
pCodecCtx->bit_rate = 400000;
AVDictionary *param = 0;
if (pCodecCtx->codec_id == AV_CODEC_ID_H264)
{
ret = av_dict_set(¶m, "preset", "slow", 0);
ret = av_dict_set(¶m, "tune", "zerolatency", 0);
}
av_dump_format(pOutputFmtCtx, 0, szOutput, 1);
const AVCodec* pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec)
return false;
ret = avcodec_open2(pCodecCtx, pCodec, ¶m);
if (ret < 0)
return false;
AVPacket* pkt = av_packet_alloc();
AVFrame* frame = av_frame_alloc();
frame->format = pCodecCtx->pix_fmt;
frame->width = pCodecCtx->width;
frame->height = pCodecCtx->height;
if (0 > av_frame_get_buffer(frame, 0))
return false;
int frameBytes = av_image_get_buffer_size(pCodecCtx->pix_fmt, frame->width, frame->height, 1);
uint8_t* yuvBuf = (uint8_t*)av_malloc(frameBytes);
int64_t beginTime = get_time();
int64_t endTime = beginTime;
int64_t allBeginTime = get_time();
int64_t allEndTime = allBeginTime;
int64_t pts = 0;
avformat_write_header(pOutputFmtCtx, nullptr);
fopen_s(&infile, szInput, "rb");
if (!infile)
return false;
for (int i = 0; ; i++)
{
memset(yuvBuf, 0, frameBytes);
if (0 > fread(yuvBuf, 1, frameBytes, infile))
break;
else if (feof(infile))
break;
ret = av_frame_make_writable(frame);
if (ret != 0) {
::printf("av_frame_make_writable failed, ret = %d\n", ret);
break;
}
int needSize = av_image_fill_arrays(frame->data, frame->linesize, yuvBuf, pCodecCtx->pix_fmt, frame->width, frame->height, 1);
if (needSize != frameBytes)
{
break;
}
pts += 40;
frame->pts = pts;
beginTime += get_time();
ret = encode2(pOutputFmtCtx, pCodecCtx, frame, pkt, outfile);
endTime = get_time();
::printf("encode time:%I64dms\r\n", endTime - beginTime);
if (ret < 0)
break;
}
encode2(pOutputFmtCtx, pCodecCtx, nullptr, pkt, outfile);
allEndTime = get_time();
printf("all encode time:%I64dms\r\n", allEndTime - allBeginTime);
av_write_trailer(pOutputFmtCtx);
// ---------------------------------------------------------------
fclose(infile);
if (yuvBuf)
av_free(yuvBuf);
avcodec_close(pCodecCtx);
av_frame_free(&frame);
av_packet_free(&pkt);
avio_close(pOutputFmtCtx->pb);
avcodec_free_context(&pCodecCtx);
printf("main finish, please enter Enter to exit.\r\n");
return true;
}
求指點啊 我這個用的新的API 直接用C的寫檔案形式 就沒問題 之后換成用av_write_frame() 執行就出現崩潰 求大佬給指點指點問題出在哪里了
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/242111.html
標籤:工具平臺和程序庫
