从零开始用QT编写一个Android投屏、PC反控软件(二)--基于FFMpeg的视频编解码基础

本文详细介绍了FFmpeg在Android投屏软件开发中的重要性,重点讲解了AVCodecContext、AVCodecParameters、AVCodec等编解码核心结构,以及H.264视频解码的示例代码,展示了FFmpeg在音视频处理和流媒体领域的强大功能。
摘要由CSDN通过智能技术生成

上一篇我们学习了Android投屏开发过程中所用到的ADB命令,本篇我们将继续学习Android投屏软件开发过程中所需要的视频编解码方面的知识。

关于FFMPEG

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它提供了录制、转换以及流化音视频的完整解决方案,包含了非常先进的音频/视频编解码库libavcodec,以保证高可移植性和编解码质量。此外,FFmpeg可以使用GPU加速,并且提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换等。它还提供了丰富的插件模块,包括封装和解封装的插件、编码与解码的插件等,可以方便地扩展其功能。
除了上述功能外,FFmpeg还提供了播放器相关功能,其avformat和avcode可以播放各种媒体文件或者流。此外,通过libavformat中的接口,可以实现音频布局转换和布局调整等功能。
总之,FFmpeg是一款功能强大的多媒体处理工具和开发套件,被广泛应用于音视频处理、流媒体传输等领域.

关键知识点

  1. AVCodecContext
    AVCodecContext 是一个描述编解码器上下文的结构体,它包含了编解码器需要的许多参数信息,这些参数信息在打开编解码器时设置。对于解码器来说,AVCodecContext 通常包含了输入数据的格式、解码后的数据格式以及其他解码相关的设置。

  2. AVCodecParameters
    AVCodecParameters 是一个描述编解码器参数的结构体,它包含了流的编解码器信息,比如编解码器的类型(视频、音频等)、编解码器的ID(指定具体的编解码器,如H.264)、位宽、帧率等。在FFmpeg中,每个流(AVStream)都有一个与之关联的 AVCodecParameters 实例,用于描述该流的编解码器参数。

  3. AVCodec
    AVCodec 是一个描述编解码器的结构体,它包含了编解码器的信息,比如编解码器的名字、类型(编码器或解码器)、支持的像素格式等。FFmpeg通过 AVCodec 结构体来注册和管理所有的编解码器。

  4. AVPacket
    AVPacket 是一个描述压缩数据的结构体,它包含了压缩数据的引用计数、数据、数据大小、时间戳等信息。在解码过程中,AVPacket 用于存储从输入流中读取的压缩数据。

  5. AVFrame
    AVFrame 是一个描述解码后原始数据的结构体,它包含了原始数据的引用计数、数据、线条数、宽度、高度等信息。在解码过程中,AVFrame 用于存储解码后的数据。

一个H.264视频解码示例

以下是一个简单的使用FFmpeg库进行H.264视频解码的示例代码。注意,这段代码只是一个基本示例,并没有进行错误处理,实际使用时需要添加适当的错误处理逻辑。

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>

int main(int argc, char* argv[]) {
if (argc < 2) {
printf(“Usage: %s \n”, argv[0]);
return -1;
}

const char* filePath = argv[1];  

// Initialize libavformat and register all muxers, demuxers, and protocols.  
av_register_all();  

// Allocate an AVFormatContext.  
AVFormatContext* pFormatContext = avformat_alloc_context();  
if (!pFormatContext)  
    return -1;  

// Open the input stream. Read the header. No AVFormatContext yet.  
if (avformat_open_input(&pFormatContext, filePath, NULL, NULL) != 0) {  
    printf("Could not open input file '%s'\n", filePath);  
    avformat_free_context(pFormatContext);  
    return -1;  
}  

// Retrieve stream information.  
if (avformat_find_stream_info(pFormatContext, NULL) < 0) {  
    printf("Could not find stream information\n");  
    avformat_close_input(&pFormatContext);  
    return -1;  
}  

int videoStreamIndex = av_find_best_stream(pFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);  
if (videoStreamIndex < 0) {  
    printf("Did not find a video stream in the input file\n");  
    avformat_close_input(&pFormatContext);  
    return -1;  
}  

// Find the decoder for the video stream.  
AVCodecParameters* pCodecParameters = pFormatContext->streams[videoStreamIndex]->codecpar;  
AVCodec* pCodec = avcodec_find_decoder(pCodecParameters->codec_id);  
if (!pCodec) {  
    printf("Unsupported codec\n");  
    avformat_close_input(&pFormatContext);  
    return -1;  
}  

// Allocate codec context.  
AVCodecContext* pCodecContext = avcodec_alloc_context3(pCodec);  
if (!pCodecContext) {  
    printf("Could not allocate video codec context\n");  
    avformat_close_input(&pFormatContext);  
    return -1;  
}  

// Copy codec parameters from input stream to output codec context.  
if (avcodec_parameters_to_context(pCodecContext, pCodecParameters) < 0) {  
    printf("Could not copy codec parameters\n");  
    avcodec_free_context(&pCodecContext);  
    avformat_close_input(&pFormatContext);  
    return -1;  
}  

// Open the codec.  
if (avcodec_open2(pCodecContext, pCodec, NULL) < 0) {  
    printf("Could not open codec\n");  
    avcodec_free_context(&pCodecContext);  
    avformat_close_input(&pFormatContext);  
    return -1;  
}  

AVFrame* frame = av_frame_alloc();  
if (!frame) {  
    printf("Could not allocate frame\n");  
    avcodec_free_context(&pCodecContext);  
    avformat_close_input(&pFormatContext);  
    return -1;  
}  

AVPacket packet;  
while (av_read_frame(pFormatContext, &packet) >= 0) {  
    if (packet.stream_index == videoStreamIndex) {  
        if (avcodec_send_packet(pCodecContext, &packet) == 0) {  
            while (avcodec_receive_frame(pCodecContext, frame) == 0) {  
                // Process decoded frame here.  
                printf("Decoded frame with size: %d x %d\n", frame->width, frame->height);  
            }  
        }  
    }  
    av_packet_unref(&packet);  
}  

// Flush the decoder (some frames might be buffered).  
avcodec_send_packet(pCodecContext, NULL);  
while (avcodec_receive_frame(pCodecContext, frame) == 0) {  
    // Process decoded frame here.  
    printf("Flushed frame with size: %d x %d\n", frame->width, frame->height);  
}  

// Clean up.  
av_frame_free(&frame);  
avcodec_free_context(&pCodecContext);  
avformat_close_input(&pFormatContext);  

return 0;  

}

更多内容请关注 github: linkedbyte

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值