FFmpeg打开x265编码器报错:Lookahead depth must be greater than the max consecutive bframe count
生活随笔
收集整理的這篇文章主要介紹了
FFmpeg打开x265编码器报错:Lookahead depth must be greater than the max consecutive bframe count
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原代碼:
#pragma warning(disable : 4996)// 2-muxing編碼視頻.cpp #include <stdio.h> #include <stdlib.h> #include <iostream> #include <string> // 字符串操作 #include <direct.h> // 文件夾 #include <stdbool.h> #include <windows.h>#ifdef __cplusplus extern "C" { // ffmpeg 相關頭文件 #endif #include <libavformat/avformat.h> //#include "libavcodec/avcodec.h" #include <libavutil/opt.h> #include "libavutil/imgutils.h" #include "libswscale/swscale.h" #ifdef __cplusplus } #endifusing namespace std;#pragma comment(lib, "avformat.lib") #pragma comment(lib, "avutil.lib") #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avfilter.lib") #pragma comment(lib, "swscale.lib") #pragma comment(lib, "swresample.lib") #pragma comment(lib, "postproc.lib") #pragma comment(lib, "avdevice.lib")/// 輸入輸出文件信息 //const char* Out_File_Name = "video.h264"; const char* Out_File_Name = "video_out.mp4";#define CODEC_FLAG_GLOBAL_HEADER (1 << 22)static void encodeMP4(AVCodecContext* enc_ctx, AVFormatContext* inFmtCtx,AVFormatContext* outFmtCtx, AVFrame* frame,AVPacket* pkt, int frameIndex);int main() {int ret;rtsp解碼配置AVFormatContext* camFmtCtx = avformat_alloc_context();AVDictionary* options = NULL;char filepath[] = "rtsp://admin:abc12345@192.168.1.67/h264/ch1/main/av_stream"; //或"rtsp://admin:abc12345@192.168.1.67:554/h264/ch1/main/av_stream"av_dict_set(&options, "buffer_size", "1024000", 0); //設置緩存大小,1080p可將值跳到最大av_dict_set(&options, "rtsp_transport", "tcp", 0); //以tcp的方式打開,av_dict_set(&options, "stimeout", "5000000", 0); //設置超時斷開鏈接時間,單位usav_dict_set(&options, "max_delay", "500000", 0); //設置最大時延 //不知道這些字典是干嘛用的,有的注釋了也能跑//int ret = avformat_open_input(&camFmtCtx, "video=Vimicro USB 2.0 PC Camera (Venus)", iformat, &options);ret = avformat_open_input(&camFmtCtx, filepath, NULL, &options);if (ret != 0){av_dict_free(&options);return -1;}av_dump_format(camFmtCtx, 0, filepath, 0); //打印文件信息/*Input #0, rtsp, from 'rtsp://admin:abc12345@192.168.1.67/h264/ch1/main/av_stream':Metadata:title : Media PresentationDuration: N/A, bitrate: N/AStream #0:0: Video: h264, none, 90k tbnStream #0:1: Audio: pcm_alaw, 8000 Hz, 1 channels, 64 kb/s*///查找輸入流ret = avformat_find_stream_info(camFmtCtx, NULL); //將流信息填充進camFmtCtx中if (ret < 0){cout << "無法獲取流的信息" << endl;return -1;}int videoindex = -1;for (int i = 0; i < camFmtCtx->nb_streams; i++){if (camFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){videoindex = i;break;}}if (videoindex == -1){printf("Didn't find a video stream.\n");return 0;}//查找攝像頭可用解碼器AVCodecContext* camDecodeCtx = camFmtCtx->streams[videoindex]->codec;AVRational time_base = camFmtCtx->streams[videoindex]->time_base;AVCodecID codecID = camFmtCtx->streams[videoindex]->codecpar->codec_id;// cout << "codecID = " << codecID << endl;AVCodec* codec = avcodec_find_decoder(codecID); //尋找codecID對應的編碼器if (codec == NULL){cout << "沒有解碼器" << endl;return -1;}ret = avcodec_open2(camDecodeCtx, codec, NULL); //打開編碼器if (ret < 0){cout << "avodec_open2 error" << endl;return -1;}cout << "解碼器打開成功" << endl;//H264編碼器,encode函數使用//AVCodecID encodeID = AV_CODEC_ID_H264;AVCodecID encodeID = AV_CODEC_ID_H265;AVCodec* encodec = avcodec_find_encoder(encodeID);//avcodec_find_encoder_by_name();if (!encodec){cout << "encodec == NULL" << endl;}AVCodecContext* encodeCtx = avcodec_alloc_context3(encodec);if (!encodeCtx){cout << "enc == NULL" << endl;}encodeCtx->bit_rate = 400000;encodeCtx->width = camDecodeCtx->width;encodeCtx->height = camDecodeCtx->height;encodeCtx->time_base = { 1, 25 };encodeCtx->framerate = { 25, 1 };encodeCtx->gop_size = 10;encodeCtx->max_b_frames = 1;encodeCtx->pix_fmt = AV_PIX_FMT_YUV420P;//加載預設av_opt_set(encodeCtx->priv_data, "preset", "slow", 0);av_opt_set(encodeCtx->priv_data, "tune", "zerolatency", 0);ret = avcodec_open2(encodeCtx, encodec, NULL);if (ret < 0){cout << "encodec open error" << endl;exit(-1);}// FILE* fp = nullptr;// fopen_s(&fp, "1.h264", "wb");// 改變為保存mp4方式AVFormatContext * outFmtCtx = nullptr;const char* fileName = "1.mp4";avformat_alloc_output_context2(&outFmtCtx, NULL, NULL, fileName);if (!outFmtCtx){printf("Could not create output context\n");return -4;}for (int i = 0; i < camFmtCtx->nb_streams; i++){AVStream* in_stream = camFmtCtx->streams[i];AVStream* out_stream = avformat_new_stream(outFmtCtx, in_stream->codec->codec);if (!out_stream){printf("Failed allocating output stream\n");return -5;}//Copy the settings of AVCodecContextif (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0){printf("Failed to copy context from input to output stream codec context\n");return -6;}out_stream->codec->codec_tag = 0;if (outFmtCtx->oformat->flags & AVFMT_GLOBALHEADER){out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;}avcodec_parameters_from_context(out_stream->codecpar, encodeCtx); //必須}av_dump_format(outFmtCtx, 0, fileName, 1);if (!(outFmtCtx->oformat->flags & AVFMT_NOFILE)){ret = avio_open(&outFmtCtx->pb, fileName, AVIO_FLAG_WRITE);if (ret < 0){printf("Could not open output file '%s'", fileName);return -7;}}if (avformat_write_header(outFmtCtx, NULL) < 0){printf("Error occurred when opening output file\n");return -8;}// 改變為保存mp4方式AVPacket * packetIn = av_packet_alloc();AVPacket* packetOut = av_packet_alloc();AVFrame* pFrameOut = av_frame_alloc();int got_picture;struct SwsContext* img_convert_ctx = sws_getContext(camDecodeCtx->width,camDecodeCtx->height,camDecodeCtx->pix_fmt,camDecodeCtx->width,camDecodeCtx->height,AV_PIX_FMT_YUV420P,/*SWS_FAST_BILINEAR*/SWS_BICUBIC, NULL, NULL, NULL);unsigned char* out_buffer = (unsigned char*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, camDecodeCtx->width,camDecodeCtx->height, 16));for (int i = 0; i < 250; i++){ret = av_read_frame(camFmtCtx, packetIn); //攝像頭取到packet,要轉為pFrameYUV的yuv格式if (ret >= 0 && packetIn->stream_index == videoindex){AVFrame* pFrameYUV = av_frame_alloc();pFrameYUV->format = AV_PIX_FMT_YUV420P;pFrameYUV->width = camDecodeCtx->width;pFrameYUV->height = camDecodeCtx->height;avpicture_fill((AVPicture*)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P,camDecodeCtx->width,camDecodeCtx->height);avcodec_decode_video2(camDecodeCtx, pFrameOut, &got_picture, packetIn);if (got_picture){sws_scale(img_convert_ctx, (const unsigned char* const*)pFrameOut->data,pFrameOut->linesize, 0,camDecodeCtx->height,pFrameYUV->data, pFrameYUV->linesize);}unsigned int untime = GetTickCount();//pFrameYUV->pts = untime;//encode(encodeCtx, pFrameYUV, packetOut, fp); //編碼yuv// 改變為保存mp4方式encodeMP4(encodeCtx, camFmtCtx, outFmtCtx, pFrameYUV, packetOut, i);// 改變為保存mp4方式av_free(pFrameYUV);}}// 改變為保存mp4方式//Write file trailerav_write_trailer(outFmtCtx);if (outFmtCtx && !(outFmtCtx->oformat->flags & AVFMT_NOFILE))avio_close(outFmtCtx->pb);avformat_free_context(outFmtCtx);//改變為保存mp4方式av_free(pFrameOut);av_packet_free(&packetIn);av_packet_free(&packetOut);sws_freeContext(img_convert_ctx);avcodec_free_context(&encodeCtx);av_free(out_buffer);//fclose(fp);//avcodec_free_context(&camDecodeCtx);avformat_close_input(&camFmtCtx);avformat_free_context(camFmtCtx);av_dict_free(&options);}static void encodeMP4(AVCodecContext* enc_ctx, AVFormatContext* inFmtCtx,AVFormatContext* outFmtCtx, AVFrame* frame,AVPacket* pkt, int frameIndex) {int ret;/* send the frame to the encoder */if (frame)printf("Send frame %3", frame->pts);ret = avcodec_send_frame(enc_ctx, frame);if (ret < 0){fprintf(stderr, "Error sending a frame for encoding\n");exit(1);}while (ret >= 0){ret = avcodec_receive_packet(enc_ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if (ret < 0){fprintf(stderr, "Error during encoding\n");exit(1);}AVStream* in_stream = inFmtCtx->streams[pkt->stream_index];AVRational timeBase = in_stream->time_base;AVStream* out_stream = outFmtCtx->streams[pkt->stream_index];///如果沒有顯示時間戳自己加上時間戳并且將顯示時間戳賦值解碼時間戳if (pkt->pts == AV_NOPTS_VALUE){//Write PTSAVRational time_base1 = timeBase;//Duration between 2 frames (us)int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);//Parameterspkt->pts = (double)(frameIndex * calc_duration) / (double)(av_q2d(time_base1) * AV_TIME_BASE);pkt->dts = pkt->pts;pkt->duration = (double)calc_duration / (double)(av_q2d(time_base1) *AV_TIME_BASE);//m_frame_index++;}//Convert PTS/DTSpkt->pts = av_rescale_q_rnd(pkt->pts, timeBase, out_stream->time_base,(AVRounding)(AV_ROUND_NEAR_INF |AV_ROUND_PASS_MINMAX));pkt->dts = av_rescale_q_rnd(pkt->dts, timeBase, out_stream->time_base,(AVRounding)(AV_ROUND_NEAR_INF |AV_ROUND_PASS_MINMAX));pkt->duration = av_rescale_q(pkt->duration, timeBase, out_stream->time_base);pkt->pos = -1;printf("Write packet %d size=%d \n", pkt->size, pkt->pts);if (av_interleaved_write_frame(outFmtCtx, pkt) < 0){printf("Error muxing packet\n");}av_packet_unref(pkt);} }
解決方法:
發現它的編碼碼率設置為40萬,即400k,我改成400萬,或者不設置(它自動選定默認值)就好了
總結
以上是生活随笔為你收集整理的FFmpeg打开x265编码器报错:Lookahead depth must be greater than the max consecutive bframe count的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: fcpx瘦身插件_FCPX必备插件大讲堂
- 下一篇: 5G网络规划新特征