Qt オーディオおよびビデオ開発 44 ローカル カメラ ストリーミング (解像度/フレーム レート/高リアルタイム パフォーマンスなどの設定をサポート)

I.はじめに

ローカル カメラ ストリーミングは、ローカル デスクトップ ストリーミングと似ていますが、コレクション デバイスのソースがデスクトップではなくローカル カメラ デバイスに置き換えられていることと、他のコードはまったく同じです。ローカル カメラからリアルタイム ビデオを収集する場合、解像度とフレーム レートを設定する場合は、デバイス自体がサポートしている必要があることに注意してください。サポートしていない場合は停止します。たとえば、最大解像度デバイス自体は 1280x720 で、1080x720 をキャプチャするように解像度を積極的に設定すると、収集できない画像は失敗します. デフォルトで設定されていない場合、通常、640x480 の解像度と 25 フレーム レートを使用して収集します. ローカル カメラ デバイスをキャプチャするコマンド ラインは、ffmpeg -f dshow -i video="USB Video Device":audio="microphone (USB Audio Device)" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f rtsp です。 rtsp:/ /192.168.0.110:6907/stream 、オーディオとビデオが利用できるように、マイクを使用するように指定できます。

一般的な収集手順:

  • フォーマット av_find_input_format、パラメーター dshow/v4l2/avfoundation を見つけます。
  • デスクトップ avformat_open_input、パラメーター video=USB ビデオ デバイスを開きます
  • ビデオ ストリームを検索 av_find_best_stream
  • デコーダーを検索 avcodec_find_decoder
  • デコーダを開く avcodec_open2
  • ループ読み取り av_read_frame
  • ビデオのデコード avcodec_send_packet/avcodec_receive_frame
  • リリースを閉じる avcodec_free_context/avformat_close_input

プッシュ フローの一般的な手順:

  • 出力を作成 avformat_alloc_output_context2
  • ビデオ ストリームの作成 avformat_new_stream
  • 出力avio_openを開き、プッシュストリームの完全なアドレスをパラメーターとして入力します
  • 書き込み開始文字 avformat_write_header
  • 書き込みフレーム データ av_interleaved_write_frame
  • リリースを閉じる avio_close/avformat_free_context

2. レンダリング

ここに画像の説明を挿入

3. 体験アドレス

  1. 国内サイト: https: //gitee.com/feiyangqingyun
  2. 国際サイト: https://github.com/feiyangqingyun
  3. 個人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体験アドレス:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g抽出コード:01jf ファイル名:bin_video_push.

4. 関連コード

void FFmpegThread::initInputFormat()
{
    
    
    //本地摄像头/桌面录屏
    if (videoType == VideoType_Camera) {
    
    
#if defined(Q_OS_WIN)
        //ifmt = av_find_input_format("vfwcap");
        ifmt = av_find_input_format("dshow");
#elif defined(Q_OS_LINUX)
        //可以打开cheese程序查看本地摄像头(如果是在虚拟机中需要设置usb选项3.1)
        //ifmt = av_find_input_format("v4l2");
        ifmt = av_find_input_format("video4linux2");
#elif defined(Q_OS_MAC)
        ifmt = av_find_input_format("avfoundation");
#endif
    } else if (videoType == VideoType_Desktop) {
    
    
#if defined(Q_OS_WIN)
        ifmt = av_find_input_format("gdigrab");
#elif defined(Q_OS_LINUX)
        ifmt = av_find_input_format("x11grab");
#elif defined(Q_OS_MAC)
        ifmt = av_find_input_format("avfoundation");
#endif
    }
}

bool FFmpegThread::initInput()
{
    
    
    //实例化格式处理上下文
    formatCtx = avformat_alloc_context();
    //设置超时回调(有些不存在的地址或者网络不好的情况下要卡很久)
    formatCtx->interrupt_callback.callback = FFmpegHelper::avinterruptCallBackFun;
    formatCtx->interrupt_callback.opaque = this;

    //打开输入(通过标志位控制回调那边做超时判断)
    //其他地方调用 formatCtx->url formatCtx->filename 可以拿到设置的地址(两个变量值一样)
    tryOpen = true;
    QByteArray urlData = VideoHelper::getRightUrl(videoType, videoUrl).toUtf8();
    int result = avformat_open_input(&formatCtx, urlData.data(), ifmt, &options);
    tryOpen = false;
    if (result < 0) {
    
    
        debug("打开出错", "错误: " + FFmpegHelper::getError(result));
        return false;
    }

    //根据自己项目需要开启下面部分代码加快视频流打开速度
    //开启后由于值太小可能会出现部分视频流获取不到分辨率
    if (decodeType == DecodeType_Fastest && videoType == VideoType_Rtsp) {
    
    
        //接口内部读取的最大数据量(从源文件中读取的最大字节数)
        //默认值5000000导致这里卡很久最耗时(可以调小来加快打开速度)
        formatCtx->probesize = 50000;
        //从文件中读取的最大时长(单位为 AV_TIME_BASE units)
        formatCtx->max_analyze_duration = 5 * AV_TIME_BASE;
        //内部读取的数据包不放入缓冲区
        //formatCtx->flags |= AVFMT_FLAG_NOBUFFER;
        //设置解码错误验证过滤花屏
        //formatCtx->error_recognition |= AV_EF_EXPLODE;
    }

    //获取流信息
    result = avformat_find_stream_info(formatCtx, NULL);
    if (result < 0) {
    
    
        debug("找流失败", "错误: " + FFmpegHelper::getError(result));
        return false;
    }

    //解码格式
    formatName = formatCtx->iformat->name;
    //某些格式比如视频流不做音视频同步(响应速度快)
    if (formatName == "rtsp" || videoUrl.endsWith(".sdp")) {
    
    
        useSync = false;
    }

    //设置了最快速度则不启用音视频同步
    if (decodeType == DecodeType_Fastest) {
    
    
        useSync = false;
    }

    //有些格式不支持硬解码
    if (formatName.contains("rm") || formatName.contains("avi") || formatName.contains("webm")) {
    
    
        hardware = "none";
    }

    //本地摄像头设备解码出来的直接就是yuv显示不需要硬解码
    if (videoType == VideoType_Camera || videoType == VideoType_Desktop) {
    
    
        useSync = false;
        hardware = "none";
    }

    //过低版本不支持硬解码
#if (FFMPEG_VERSION_MAJOR < 3)
    hardware = "none";
#endif

    //获取文件时长(这里获取到的是秒)
    double length = (double)formatCtx->duration / AV_TIME_BASE;
    duration = length * 1000;
    this->checkVideoType();

    //有时候网络地址也可能是纯音频
    if (videoType == VideoType_FileHttp) {
    
    
        onlyAudio = VideoHelper::getOnlyAudio(videoUrl, formatName);
    }

    if (getIsFile()) {
    
    
        //文件必须要音视频同步
        useSync = true;
        //发送文件时长信号
        emit receiveDuration(duration > 0 ? duration : 0);
    }

    QString msg = QString("格式: %1 时长: %2 秒 加速: %3").arg(formatName).arg(duration / 1000).arg(hardware);
    debug("媒体信息", msg);
    return true;
}

5. 特長

5.1 ファイルストリーミング

  1. ネットワーク カードとリッスン ポートを指定し、ネットワーク リクエストを受信して​​、オーディオやビデオなどのさまざまなファイルをプッシュします。
  2. リアルタイム統計には、各ファイルに対応する訪問数、合計訪問数、および異なる IP アドレスからの訪問数が表示されます。
  3. 0-ダイレクトプレイ、1-ダウンロードプレイの複数モードを指定可能。
  4. リアルタイム印刷では、さまざまな送受信要求および応答データが表示されます。
  5. 各ファイルは MD5 で暗号化された一意の識別子に対応しており、アクセスするファイルを識別するためにアドレス サフィックスを要求するために使用されます。
  6. さまざまなブラウザー (Google chromium/Microsoft edge/Firefox firefox など)、さまざまなプレーヤー (vlc/mpv/ffplay/potplayer/mpchc など) をサポートして、リクエストを開きます。
  7. 再生処理中は、再生の進行を任意に切り替えることができ、倍速再生に対応しています。
  8. ストリーミングが必要なファイルの名前履歴が自動的に保存され、アプリケーションをロードするために開かれます。
  9. ファイルを切り替えてアクセスアドレスを取得し、アドレスをクリップボードに自動的にコピーして、直接貼り付けてテストします。
  10. 非常に低い CPU 使用率、128 チャンネル 1080P 同時ストリーミングは 1% 未満の CPU 使用率、非同期データ送信メカニズムです。
  11. 純粋な QTcpSocket 通信は、ストリーミング メディア サービス プログラムに依存しません。コア ソース コードは 500 行未満で、詳細な注釈と完全な機能を備えています。
  12. Qt4/Qt5/Qt6 の任意のバージョンをサポートし、任意のシステム (windows/linux/macos/android/embedded linux など) をサポートします。

5.2 ネットワークストリーミング

  1. さまざまなローカル ビデオ ファイルとネットワーク ビデオ ファイルをサポートします。
  2. さまざまなネットワーク ビデオ ストリーム、Web カメラ、rtsp、rtmp、http などのプロトコルをサポートします。
  3. ローカル カメラ デバイスのストリーミングをサポートし、解像度とフレーム レートを指定できます。
  4. 画面領域やフレーム レートなどを指定して、ローカル デスクトップのストリーミングをサポートします。
  5. ストリーミング メディア サービス プログラム、デフォルトの mediamtx (以前の rtsp-simple-server) を自動的に開始します。srs、EasyDarwin、LiveQing、ZLMediaKit などを選択できます。
  6. 動画ファイルをリアルタイムで切り替えてプレビューできます。
  7. ストリーミングの明瞭度と品質を調整できます。
  8. ファイル、ディレクトリ、およびアドレスを動的に追加できます。
  9. ビデオ ファイルは自動的にループでストリーミングされます。ビデオ ソースがビデオ ストリームの場合、切断された後、自動的に再接続されます。
  10. ネットワーク ビデオ ストリームは自動的に再接続され、再接続は成功し、ストリーミングは自動的に続行されます。
  11. ネットワークビデオストリーミングのリアルタイム性は非常に高く、遅延は非常に少なく、遅延時間は約100msです。
  12. ストリームをプッシュした後、rtmp アドレスを使用してアクセスするほか、直接 hls/webrtc アクセスにも対応し、ブラウザを直接開いてリアルタイム画面を表示できます。
  13. Qt4/Qt5/Qt6 の任意のバージョンをサポートし、任意のシステム (windows/linux/macos/android/embedded linux など) をサポートします。

おすすめ

転載: blog.csdn.net/feiyangqingyun/article/details/130500363