请教 FFmpeg中的 avcodec_send_frame 为什么返回为-22

归途醉染 2019-02-28 09:12:36
代码如下: FFmpeg版本为4.0


int main(int argc, char* argv[])
{

AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
int ret1 = 0;

AVCodecContext *pH264CodecCtx;
AVCodec *pH264Codec;

av_register_all();
avformat_network_init();
avdevice_register_all();//Register Device




pFormatCtx = avformat_alloc_context();


//Use gdigrab
AVDictionary* options = NULL;

AVInputFormat *ifmt = av_find_input_format("gdigrab");
if (avformat_open_input(&pFormatCtx, "desktop", ifmt, &options) != 0) {
printf("Couldn't open input stream.\n");
return -1;
}



if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Couldn't find stream information.\n");
return -1;
}

videoindex = -1;

for (i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoindex = i;
}
}

if (videoindex == -1)
{
printf("Couldn't find a video stream.\n");
return -1;
}

pCodecCtx = pFormatCtx->streams[videoindex]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

if (pCodec == NULL)
{
printf("Codec not found.\n");
return -1;
}

if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Could not open codec.\n");
return -1;
}




AVFrame *pFrame, *pFrameYUV;
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
uint8_t *out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);

int ret, got_picture;

AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
AVPacket *packetH264 = (AVPacket *)av_malloc(sizeof(AVPacket));
FILE *fp_yuv = fopen("output.yuv", "wb");
FILE *fp_h264 = fopen("output.h264", "wb");
struct SwsContext *img_convert_ctx;
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

///这里打印出视频的宽高
fprintf(stderr, "w= %d h= %d\n", pCodecCtx->width, pCodecCtx->height);

// 查找h264 从这里就和解码不一样了
pH264Codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!pH264Codec)
{
fprintf(stderr, "h254 codec not find");
return -1;
}
pH264CodecCtx = avcodec_alloc_context3(pH264Codec);

pH264CodecCtx->codec_id = AV_CODEC_ID_H264;
pH264CodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pH264CodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pH264CodecCtx->width = pCodecCtx->width;
pH264CodecCtx->height = pCodecCtx->height;
pH264CodecCtx->time_base.num = 1;
pH264CodecCtx->time_base.den = 15;
pH264CodecCtx->bit_rate= 400000; //比特率(调节这个大小可以改变编码后视频的质量)
pH264CodecCtx->gop_size = 12;

//H264 还可以设置很多参数 自行研究吧
//// pCodecCtx->me_range = 16;
//// pCodecCtx->max_qdiff = 4;
//// pCodecCtx->qcompress = 0.6;
//// pCodecCtx->qmin = 10;
//// pCodecCtx->qmax = 51;
// pCodecCtx->me_range = 16;
// pCodecCtx->max_qdiff = 1;
// pCodecCtx->qcompress = 0.6;
// pCodecCtx->qmin = 10;
// pCodecCtx->qmax = 51;
// //Optional Param
// pCodecCtx->max_b_frames=3;
pH264CodecCtx->qmin = 10;
pH264CodecCtx->qmax = 51;

if (pH264CodecCtx->flags & AVFMT_GLOBALHEADER)
{
pH264CodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

AVDictionary *param = NULL;

//H264
//av_dict_set(¶m, "preset", "slow", 0);
av_dict_set(¶m, "preset", "superfast", 0);
av_dict_set(¶m, "tune", "zerolatency", 0); //实现实时编码

pH264Codec = avcodec_find_decoder(pH264CodecCtx->codec_id);
if (!pH264Codec)
{
fprintf(stderr, "Can not find video encodec");
return -1;
}
if (avcodec_open2(pH264CodecCtx, pH264Codec, ¶m) < 0)
{
printf("FAILD to open video encodec.\n");
return -1;
}
//我们就读取图像
for (;;)
{
if (av_read_frame(pFormatCtx, packet) < 0)
{
break;
}

if (packet->stream_index == videoindex)
{
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);

if (ret < 0) {
printf("Decode Error.\n");
return -1;
}

if (got_picture)
{

sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);

/* SDL_UpdateYUVTexture(Texture, NULL,
pFrameYUV->data[0], pFrameYUV->linesize[0],
pFrameYUV->data[1], pFrameYUV->linesize[1],
pFrameYUV->data[2], pFrameYUV->linesize[2]);*/
int y_size = pCodecCtx->width*pCodecCtx->height;
fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv); //Y
fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv); //U
fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv); //V

/* SDL_RenderClear(render);
SDL_RenderCopy(render, Texture, NULL, &rect);
SDL_RenderPresent(render);*/

//编码成h264
/* int ret1 = avcodec_encode_video2(pH264CodecCtx, packet, pFrameYUV, &got_picture);
if (ret1<0)
{
printf("avcodec_encode_video2 failed.\n");
return -1;
}*/
if (pFrame)
{
printf("send frame %lld\n", pFrame->pts);
}
ret1 = avcodec_send_frame(pH264CodecCtx, pFrame);
if (ret1 < 0 && ret1 != AVERROR(EAGAIN) && ret1 != AVERROR_EOF)
{
/* ret = avcodec_receive_frame(aCodecCtx, frame);
if (ret < 0 && ret != AVERROR_EOF)
return -1;)*/

fprintf(stderr, "error sending a frame for Encodec.");
return -1;
}
while (ret1>=0)
{
ret1 = avcodec_receive_packet(pH264CodecCtx, packet);
if (ret1==AVERROR(EAGAIN)||ret1==AVERROR_EOF)
{
av_packet_unref(packet);
return -1;
}
else if (ret < 0) {
fprintf(stderr, "Error during encoding\n");
exit(1);
}
ret1 = fwrite(packet->data, 1, packet->size, fp_h264);
if (0 > ret1)
{
printf("write into output.h264 failed.\n");
return -1;
}
}

}
}
av_free_packet(packet);
}

sws_freeContext(img_convert_ctx);


fclose(fp_yuv);
fclose(fp_h264);

av_free(out_buffer);
av_free(pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);

return 0;
}


多谢大家!

...全文
2049 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
keefor 2019-07-23
  • 打赏
  • 举报
回复 2
pH264Codec = avcodec_find_decoder(AV_CODEC_ID_H264); 用解码器去编码?你是故意这么写的吗?
一个纸杯 2021-11-18
  • 举报
回复
@keefor 感谢,为啥我也是这样写的,奇怪了
归途醉染 2019-03-01
  • 打赏
  • 举报
回复
没人吗? 我发错地方了吗?
归途醉染 2019-03-01
  • 打赏
  • 举报
回复


引用 3 楼 pstrunner 的回复:
查看官方的API说明啊,搜索一下。自己学会去查找资料,这样你会进步更快。
我搞定了, 谢谢 把139到144注释就好了

  pH264Codec = avcodec_find_decoder(pH264CodecCtx->codec_id);
    if (!pH264Codec)
    {
        fprintf(stderr, "Can not find video encodec");
        return -1;
    }
pstrunner 2019-03-01
  • 打赏
  • 举报
回复
查看官方的API说明啊,搜索一下。自己学会去查找资料,这样你会进步更快。
归途醉染 2019-02-28
  • 打赏
  • 举报
回复
大佬们 求解答鸭...

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧