記事ディレクトリ
序文
この記事では、FFmpeg 関数ライブラリを使用して QT 環境でローカル ビデオをデコードする方法 (パート 2) - ローカル ビデオをデコードし、ウィンドウで再生する方法を共有します。
1.FFmpegのデコード処理
- 下図はデコードのフローチャートで、黄色の部分がデコードで呼び出される関数、緑色の部分がデコードに必要なパラメータ(構造体)です。
2. デコードと再生の効果
- ローカル ビデオがデコードされた後、次の図に示すように、デコードされたビデオ フレームがウィンドウで再生されます。
3.具体的な手順とソースコード
1. FFmpeg ヘッダー ファイル リファレンス
//当前C++兼容C语言
extern "C"
{
//avcodec:编解码(最重要的库)
#include <libavcodec/avcodec.h>
//avformat:封装格式处理
#include <libavformat/avformat.h>
//swscale:视频像素数据格式转换
#include <libswscale/swscale.h>
//avdevice:各种设备的输入输出
#include <libavdevice/avdevice.h>
//avutil:工具库(大部分库都需要这个库的支持)
#include <libavutil/avutil.h>
}
2. 環境登録
- ハードウェア デバイス、ネットワーク レジスタ、マルチプレクサ、エンコーダなどを登録する必要があります。
//环境注册
av_register_all(); //复用器、编码器等注册
avdevice_register_all(); //硬件设备注册
avformat_network_init(); //网络注册
3. カプセル化形式のコンテキストを作成する
- 関数 avformat_alloc_context() を使用して、カプセル化形式のコンテキストを作成および初期化します。
AVFormatContext *formatContext = avformat_alloc_context();
4. マルチメディア ファイルを開く
- ローカル ファイルをカプセル化形式のコンテキストで開きます。オープンに失敗すると、エラー メッセージが出力されます。
int avformat_open_ret = avformat_open_input(&formatContext,filename.toLatin1(),NULL,NULL);
if(avformat_open_ret < 0)
{
char *result = new char[64];
av_strerror(avformat_open_ret,result,64);
qDebug() << QString("错误信息:%1").arg(result);
}
qDebug() << "打开多媒体文件成功!";
5. オーディオおよびビデオ ストリーム情報を取得する
- カプセル化形式のコンテキストでオーディオおよびビデオ ストリーム情報を取得します。取得に失敗すると、エラー メッセージが表示されます。
int avformat_find_ret = avformat_find_stream_info(formatContext,NULL);
if(avformat_find_ret < 0)
{
char *result = new char[64];
av_strerror(avformat_open_ret,result,64);
qDebug() << QString("错误信息:%1").arg(result);
}
qDebug() << "获取音视频流信息成功!";
6. ビデオ ストリームを見つける
- ビデオ ストリームを検索し、カプセル化形式のコンテキストですべてのストリーム情報をトラバースして、ビデオ ストリーム インデックスを保存します。
int streamIndex = -1;
for(int i=0;i<formatContext->nb_streams;i++)
{
if(formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
streamIndex = i;
break;
}
}
if(streamIndex == -1)
{
qDebug() << "找不到相应的流信息!";
}
7. デコーダーのコンテキストを取得する
- ビデオ ストリーム インデックスを介してデコーダ コンテキストを取得します。
AVCodecContext *codecContext = formatContext->streams[streamIndex]->codec;
8. 適切なデコーダーを見つける
- デコード コンテキストの属性 ID で適切なデコーダを見つけます。
AVCodec *codec = avcodec_find_decoder(codecContext->codec_id);
if(codec == NULL)
{
qDebug() << "找不到合适的解码器!";
}
9. デコーダーを開きます
- デコーダーのコンテキストで、見つかったデコーダーを開きます。
int avcodec_open_ret = avcodec_open2(codecContext,codec,NULL);
if(avcodec_open_ret < 0)
{
char *result = new char[64];
av_strerror(avformat_open_ret,result,64);
qDebug() << QString("错误信息:%1").arg(result);
}
qDebug() << "打开解码器成功!";
10. データコンテナの初期化
- 受信したデータのデータ パケット、データ フレーム、およびデータ バッファー コンテナーにメモリ領域を動的に割り当てます。
//数据包初始化
AVPacket *packet = av_packet_alloc();
//输入视频帧初始化
AVFrame *frame = av_frame_alloc();
//输出RGB帧初始化
AVFrame *frameRGB = av_frame_alloc();
//给缓冲区动态分配内存
uint8_t *pOutbuffer = (uint8_t*)av_malloc(avpicture_get_size(AV_PIX_FMT_RGB32,codecContext->width,codecContext->height));
//初始化缓冲区
avpicture_fill((AVPicture *)frameRGB, pOutbuffer,AV_PIX_FMT_RGB32, codecContext->width,codecContext->height);
11. 画像変換コンテキストを取得する
- デコーダ コンテキストを介して画像変換コンテキストを取得します。
SwsContext *sws = sws_getContext(codecContext->width,codecContext->height,codecContext->pix_fmt,
codecContext->width,codecContext->height,AV_PIX_FMT_RGB32,
SWS_BICUBIC,NULL,NULL,NULL);
12. ビデオ フレームの読み取りと表示
- カプセル化形式のコンテキストからデータ パケットに情報を読み取り、次にデータ パケットからデータ フレームに読み取り、最後にデータを画像に変換して表示します。
//计算解码帧数
int frameNum = 0;
//创建标签显示图像
QLabel *imgLabel = new QLabel(this);
imgLabel ->setGeometry(0,0,600,330);
//读取视频帧
while(av_read_frame(formatContext,packet) >= 0)
{
if(packet->stream_index == streamIndex)
{
avcodec_send_packet(codecContext,packet);
int decode_video_ret = avcodec_receive_frame(codecContext,frame);
if(decode_video_ret >= 0)
{
//计算帧数
frameNum++;
qDebug() << QString("正在解码播放第%1帧数据").arg(frameNum);
//视频流数据转换为RGB图像数据
sws_scale(sws, (const unsigned char* const*)frame->data,frame->linesize, 0,
codecContext->height,frameRGB->data,frameRGB->linesize);
//数据转换为图像
QImage *tmpImg = new QImage((uchar *)pOutbuffer,codecContext->width,
codecContext->height,QImage::Format_RGB32);
//加载到标签中显示
imgLabel->setPixmap(QPixmap::fromImage(img));
imgLabel->setScaledContents(true);
}
}
}
四、FFmpeg参考資料
著作権表示: この記事の内容の一部は、参照および使用のために、CSDN ブロガー "Lei Xiaohua" の元の記事を参照して編集されています。
ブログアドレス: https://blog.csdn.net/leixiaohua1020?type=blog .
要約する
以上がFFmpegの分かりやすい学習(04)~QT+FFmpegでローカル動画をデコードする(後編)の全内容ですので、読んで少しでも何かを得られれば幸いです!オリジナリティは簡単ではありません。転載のソースを示してください。記事に誤りがある場合は、読者がメッセージを残して修正し、批判することを歓迎します。