`
[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
` 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(1000*24); #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