您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Qt如何實現視頻流播放ffmpeg內核”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Qt如何實現視頻流播放ffmpeg內核”這篇文章吧。
好久以前就寫過這個工具,后來因為Qt版本的不斷升級以及ffmpeg也經歷過好多次的迭代,可能從官網下載的ffmpeg搭配原來的代碼不能正確編譯,因為很多api已經變了,所以這次特意抽空全部整理重寫一遍,只求最精簡最好用,同時兼容了ffmpeg3和ffmpeg4,并且同時支持32位的庫和64位的庫,這樣任何小白拿過去直接編譯就能用。
第一步:引入ffmpeg的頭文件
//必須加以下內容,否則編譯不能通過,為了兼容C和C99標準 #ifndef INT64_C #define INT64_C #define UINT64_C #endif //引入ffmpeg頭文件 extern "C" { #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/frame.h" #include "libavutil/pixdesc.h" #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/ffversion.h" #include "libavcodec/avcodec.h" #include "libswscale/swscale.h" #include "libavformat/avformat.h" #include "libavfilter/avfilter.h" #ifdef ffmpegdevice #include "libavdevice/avdevice.h" #endif #ifndef gcc45 #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_qsv.h" #endif }
第二步:注冊ffmpeg的庫 這里發現很多人每個類都注冊一次,搞得內存每次增加很多,不是不可以,而是沒有必要,其實ffmpeg的庫和解碼器等,在一個程序中只需要注冊一次即可,沒必要每個視頻類都注冊一次。
//一個軟件中只需要初始化一次就行 void FFmpegThread::initlib() { static QMutex mutex; QMutexLocker locker(&mutex); static bool isInit = false; if (!isInit) { //注冊庫中所有可用的文件格式和解碼器 av_register_all(); //注冊所有設備,主要用于本地攝像機播放支持 #ifdef ffmpegdevice avdevice_register_all(); #endif //初始化網絡流格式,使用網絡流時必須先執行 avformat_network_init(); isInit = true; qDebug() << TIMEMS << "init ffmpeg lib ok" << " version:" << FFMPEG_VERSION; #if 0 //輸出所有支持的解碼器名稱 QStringList listCodeName; AVCodec *code = av_codec_next(NULL); while (code != NULL) { listCodeName << code->name; code = code->next; } qDebug() << TIMEMS << listCodeName; #endif } }
第三步:設置參數
//在打開碼流前指定各種參數比如:探測時間/超時時間/最大延時等 //設置緩存大小,1080p可將值調大 av_dict_set(&options, "buffer_size", "8192000", 0); //以tcp方式打開,如果以udp方式打開將tcp替換為udp av_dict_set(&options, "rtsp_transport", "tcp", 0); //設置超時斷開連接時間,單位微秒,3000000表示3秒 av_dict_set(&options, "stimeout", "3000000", 0); //設置最大時延,單位微秒,1000000表示1秒 av_dict_set(&options, "max_delay", "1000000", 0); //自動開啟線程數 av_dict_set(&options, "threads", "auto", 0);
第四步:打開視頻流 具體代碼比較多,詳細代碼請自行開源主頁下載。
第五步:解碼圖像
void FFmpegThread::run() { //計時 QTime time; while (!stopped) { //根據標志位執行初始化操作 if (isPlay) { this->init(); isPlay = false; continue; } time.restart(); if (av_read_frame(avFormatContext, avPacket) >= 0) { //判斷當前包是視頻還是音頻 int packetSize = avPacket->size; int index = avPacket->stream_index; if (index == videoStreamIndex) { //解碼視頻流 avcodec_decode_video2(videoCodec, avFrame2, &frameFinish, avPacket); if (frameFinish) { //將數據轉成一張圖片 sws_scale(swsContext, (const uint8_t *const *)avFrame2->data, avFrame2->linesize, 0, videoHeight, avFrame3->data, avFrame3->linesize); //以下兩種方法都可以 //QImage image(avFrame3->data[0], videoWidth, videoHeight, QImage::Format_RGB32); QImage image((uchar *)buffer, videoWidth, videoHeight, QImage::Format_RGB32); if (!image.isNull()) { emit receiveImage(image); } msleep(1); } } else if (index == audioStreamIndex) { //解碼音頻流,這里暫不處理,以后交給sdl播放 } } av_packet_unref(avPacket); av_freep(avPacket); msleep(1); } //線程結束后釋放資源 free(); stopped = false; isPlay = false; qDebug() << TIMEMS << "stop ffmpeg thread"; }
以上是“Qt如何實現視頻流播放ffmpeg內核”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。