Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10.13例子改成屏幕,报错 #9

Open
yundmb opened this issue Feb 26, 2024 · 0 comments
Open

10.13例子改成屏幕,报错 #9

yundmb opened this issue Feb 26, 2024 · 0 comments

Comments

@yundmb
Copy link

yundmb commented Feb 26, 2024

`

int flush_encoder(AVFormatContext *fmtCtx, AVCodecContext *codecCtx, int vStreamIndex) {
 int ret = 0;
 AVPacket *enc_pkt = av_packet_alloc();
 enc_pkt->data = NULL;
 enc_pkt->size = 0;

 if (!(codecCtx->codec->capabilities & AV_CODEC_CAP_DELAY))
 return 0;

 printf("Flushing stream #%u encoder\n", vStreamIndex);
 if (avcodec_send_frame(codecCtx, 0) >= 0) {
 while (avcodec_receive_packet(codecCtx, enc_pkt) >= 0) {
 printf("success encoder 1 frame.\n");

 // parpare packet for muxing
 enc_pkt->stream_index = vStreamIndex;
 av_packet_rescale_ts(enc_pkt, codecCtx->time_base,
 fmtCtx->streams[vStreamIndex]->time_base);
 ret = av_interleaved_write_frame(fmtCtx, enc_pkt);
 if (ret < 0) {
 break;
 }
 }
 }

 av_packet_unref(enc_pkt);

 return ret;
}

int main() {
 int ret = 0;
 avdevice_register_all();

 AVFormatContext *inFmtCtx = avformat_alloc_context();
 AVCodecContext *inCodecCtx = NULL;
 const AVCodec *inCodec = NULL;
 AVPacket *inPkt = av_packet_alloc();
 AVFrame *srcFrame = av_frame_alloc();
 AVFrame *yuvFrame = av_frame_alloc();

 //打开输出文件,并填充fmtCtx数据
 AVFormatContext *outFmtCtx = avformat_alloc_context();
 const AVOutputFormat *outFmt = NULL;
 AVCodecContext *outCodecCtx = NULL;
 const AVCodec *outCodec = NULL;
 AVStream *outVStream = NULL;

 AVPacket *outPkt = av_packet_alloc();

 struct SwsContext *img_ctx = NULL;

 int inVideoStreamIndex = -1;

 do {
 /////////////解码器部分//////////////////////
 //打开摄像头
#ifdef _WIN32
 const AVInputFormat *inFmt = av_find_input_format("gdigrab");
 if (avformat_open_input(&inFmtCtx, "desktop", inFmt, NULL) < 0) {
 printf("Cannot open camera.\n");
 break;
 }
#elif __linux__
 AVInputFormat *inFmt = av_find_input_format("v4l2");
 if(avformat_open_input(&inFmtCtx,"/dev/video0",inFmt,NULL)<0){
 printf("Cannot open camera.\n");
 break;
 }
#endif

 if (avformat_find_stream_info(inFmtCtx, NULL) < 0) {
 printf("Cannot find any stream in file.\n");
 break;
 }

 for (uint32_t i = 0; i < inFmtCtx->nb_streams; i++) {
 if (inFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
 inVideoStreamIndex = i;
 break;
 }
 }
 if (inVideoStreamIndex == -1) {
 printf("Cannot find video stream in file.\n");
 break;
 }

 AVCodecParameters *inVideoCodecPara = inFmtCtx->streams[inVideoStreamIndex]->codecpar;
 if (!(inCodec = avcodec_find_decoder(inVideoCodecPara->codec_id))) {
 printf("Cannot find valid video decoder.\n");
 break;
 }
 if (!(inCodecCtx = avcodec_alloc_context3(inCodec))) {
 printf("Cannot alloc valid decode codec context.\n");
 break;
 }
 if (avcodec_parameters_to_context(inCodecCtx, inVideoCodecPara) < 0) {
 printf("Cannot initialize parameters.\n");
 break;
 }

 if (avcodec_open2(inCodecCtx, inCodec, NULL) < 0) {
 printf("Cannot open codec.\n");
 break;
 }

 img_ctx = sws_getContext(inCodecCtx->width,
 inCodecCtx->height,
 inCodecCtx->pix_fmt,
 inCodecCtx->width,
 inCodecCtx->height,
 AV_PIX_FMT_YUV420P,
 SWS_BICUBIC,
 NULL, NULL, NULL);

 int numBytes = av_image_get_buffer_size(AV_PIX_FMT_YUV420P,
 inCodecCtx->width,
 inCodecCtx->height, 1);
 uint8_t *out_buffer = (unsigned char *) av_malloc(numBytes * sizeof(unsigned char));

 ret = av_image_fill_arrays(yuvFrame->data,
 yuvFrame->linesize,
 out_buffer,
 AV_PIX_FMT_YUV420P,
 inCodecCtx->width,
 inCodecCtx->height,
 1);
 if (ret < 0) {
 printf("Fill arrays failed.\n");
 break;
 }
 //////////////解码器部分结束/////////////////////

 //////////////编码器部分开始/////////////////////
 const char *outFile = "camera.mp4";

 if (avformat_alloc_output_context2(&outFmtCtx, NULL, "mp4", outFile) < 0) {
 printf("Cannot alloc output file context.\n");
 break;
 }
 outFmt = outFmtCtx->oformat;

 //打开输出文件
 if (avio_open(&outFmtCtx->pb, outFile, AVIO_FLAG_READ_WRITE) < 0) {
 printf("output file open failed.\n");
 break;
 }

 //创建h264视频流,并设置参数
 outVStream = avformat_new_stream(outFmtCtx, outCodec);
 if (outVStream == NULL) {
 printf("create new video stream fialed.\n");
 break;
 }
 outVStream->time_base.den = 60;
 outVStream->time_base.num = 1;

 //编码参数相关
 AVCodecParameters *outCodecPara = outFmtCtx->streams[outVStream->index]->codecpar;
 outCodecPara->codec_type = AVMEDIA_TYPE_VIDEO;
 outCodecPara->codec_id = outFmt->video_codec;
 outCodecPara->width = 1920;
 outCodecPara->height = 1080;
 outCodecPara->bit_rate = 110000;

 //查找编码器
 outCodec = avcodec_find_encoder(outFmt->video_codec);
 if (outCodec == NULL) {
 printf("Cannot find any encoder.\n");
 break;
 }

 //设置编码器内容
 outCodecCtx = avcodec_alloc_context3(outCodec);
 avcodec_parameters_to_context(outCodecCtx, outCodecPara);
 if (outCodecCtx == NULL) {
 printf("Cannot alloc output codec content.\n");
 break;
 }
 outCodecCtx->codec_id = outFmt->video_codec;
 outCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
 outCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
 outCodecCtx->width = inCodecCtx->width;
 outCodecCtx->height = inCodecCtx->height;
 outCodecCtx->time_base.num = 1;
 outCodecCtx->time_base.den = 60;
 outCodecCtx->bit_rate = 110000;
 outCodecCtx->gop_size = 10;

 if (outCodecCtx->codec_id == AV_CODEC_ID_H264) {
 outCodecCtx->qmin = 10;
 outCodecCtx->qmax = 51;
 outCodecCtx->qcompress = (float) 0.6;
 } else if (outCodecCtx->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
 outCodecCtx->max_b_frames = 2;
 } else if (outCodecCtx->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
 outCodecCtx->mb_decision = 2;
 }

 //打开编码器
 if (avcodec_open2(outCodecCtx, outCodec, NULL) < 0) {
 printf("Open encoder failed.\n");
 break;
 }
 ///////////////编码器部分结束////////////////////

 ///////////////编解码部分//////////////////////
 yuvFrame->format = outCodecCtx->pix_fmt;
 yuvFrame->width = outCodecCtx->width;
 yuvFrame->height = outCodecCtx->height;

 ret = avformat_write_header(outFmtCtx, NULL);

 int count = 0;
 while (av_read_frame(inFmtCtx, inPkt) >= 0 && count < 50) {
 if (inPkt->stream_index == inVideoStreamIndex) {
 if (avcodec_send_packet(inCodecCtx, inPkt) >= 0) {
 while ((ret = avcodec_receive_frame(inCodecCtx, srcFrame)) >= 0) {
 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
 return -1;
 else if (ret < 0) {
 fprintf(stderr, "Error during decoding\n");
 exit(1);
 }
 sws_scale(img_ctx,
 (const uint8_t *const ) srcFrame->data,
 srcFrame->linesize,
 0, inCodecCtx->height,
 yuvFrame->data, yuvFrame->linesize);

 yuvFrame->pts = srcFrame->pts;
 //encode
 if (avcodec_send_frame(outCodecCtx, yuvFrame) >= 0) {
 if (avcodec_receive_packet(outCodecCtx, outPkt) >= 0) {
 printf("encode %d frame.\n", count);
 ++count;
 outPkt->stream_index = outVStream->index;
 av_packet_rescale_ts(outPkt, outCodecCtx->time_base,
 outVStream->time_base);
 outPkt->pos = -1;
 av_interleaved_write_frame(outFmtCtx, outPkt);
 av_packet_unref(outPkt);
 }
 }
#ifdef _WIN32
 Sleep(24);//延时24毫秒
#elif __linux__
 usleep(100024);
#endif
 }
 }
 av_packet_unref(inPkt);
 fflush(stdout);
 }
 }

 ret = flush_encoder(outFmtCtx, outCodecCtx, outVStream->index);
 if (ret < 0) {
 printf("flushing encoder failed.\n");
 break;
 }

 av_write_trailer(outFmtCtx);
 ////////////////编解码部分结束////////////////
 } while (0);

 ///////////内存释放部分/////////////////////////
 av_packet_free(&inPkt);
 avcodec_free_context(&inCodecCtx);
 avcodec_close(inCodecCtx);
 avformat_close_input(&inFmtCtx);
 av_frame_free(&srcFrame);
 av_frame_free(&yuvFrame);

 av_packet_free(&outPkt);
 avcodec_free_context(&outCodecCtx);
 avcodec_close(outCodecCtx);
 avformat_close_input(&outFmtCtx);

 return 0;
}

`
[gdigrab @ 00000200744161c0] Capturing whole desktop as 1920x1080x32 at (0,0)
[gdigrab @ 00000200744161c0] Stream #0: not enough frames to estimate rate; consider increasing probesize
[mpeg4 @ 0000020077990140] time_incr 28484223107072 too large
[mpeg4 @ 0000020077990140] time_incr 28484223108885 too large
[mpeg4 @ 0000020077990140] time_incr 28484223109141 too large
[mpeg4 @ 0000020077990140] time_incr 28484223109138 too large
[mpeg4 @ 0000020077990140] time_incr 28484223109359 too large
[mpeg4 @ 0000020077990140] time_incr 28484223108843 too large
[mpeg4 @ 0000020077990140] time_incr 28484223109364 too large
[mpeg4 @ 0000020077990140] time_incr 28484223109107 too large
[mpeg4 @ 0000020077990140] time_incr 28484223108890 too large
[mpeg4 @ 0000020077990140] time_incr 28484223108883 too large

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant