ffmpeg实现视频解码

这篇具有很好参考价值的文章主要介绍了ffmpeg实现视频解码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)

雷神的代码用在VS2022编译需要做些调整

平台环境:windows VS 2022

#pragma comment(lib, "legacy_stdio_definitions.lib") //此为添加的代码
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
#include "SDL2/SDL.h"
	FILE __iob_func[3] = { *stdin,*stdout,*stderr };
};

以及在
项目->项目属性->链接器->命令行,在右侧其他选项中添加“/SAFESEH:NO”,这样就不会再报错了。

使用ffmpeg进行解码的一般步骤

1.初始化FFmpeg库:

在代码中引入相关的FFmpeg头文件,并调用初始化函数。例如:

av_register_all();
avcodec_register_all();
avformat_network_init();

2.打开输入文件:

使用avformat_open_input,avformat_open_input 函数是FFmpeg(一个开源的多媒体处理库)中的一个函数,用于打开音视频文件或者网络流,并将其封装格式的相关信息填充到一个 AVFormatContext 结构体中。这个函数通常是在处理音视频文件时的初始步骤之一。

AVFormatContext *pFormatCtx;
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

参数解释:
ps: 用于存储 AVFormatContext 结构体指针的指针。AVFormatContext 是一个保存音视频文件或流相关信息的结构体,就是句柄。

url: 要打开的音视频文件或者网络流的URL。

fmt: 指定输入格式。通常可以设置为 NULL,表示由FFmpeg自动检测输入格式。

options: 一个指向 AVDictionary 结构体指针的指针,用于传递附加的选项。可以为 NULL,表示没有额外选项。

3.获取流信息

使用 avformat_find_stream_info函数,avformat_find_stream_info 函数是FFmpeg库中用于获取音视频流详细信息的函数。在打开音视频文件或者网络流后,通常需要调用这个函数来获取音视频流的相关信息,如编码格式、分辨率、帧率等。

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

参数解释:
ic: AVFormatContext 结构体,它包含了音视频文件或者网络流的相关信息,通常是通过 avformat_open_input 打开的。

options: 一个指向 AVDictionary 结构体指针的指针,用于传递附加的选项。可以为 NULL,表示没有额外选项。

函数返回值是一个整数,表示函数执行的结果。通常,如果函数成功执行,则返回 0,否则返回一个负数表示错误。

4.找到视频流索引并获取解码器上下文:

通过遍历流信息,找到视频流的索引,然后获取视频解码器的上下文。

int videoStreamIndex = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++) {
    if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        videoStreamIndex = i;
        break;
    }
}
AVCodecContext *pCodecCtx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStreamIndex]->codecpar);

5.查找并打开解码器:

使用avcodec_find_decoder函数查找合适的解码器,并使用avcodec_open2打开解码器。

AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
avcodec_open2(pCodecCtx, pCodec, NULL);

6.创建帧和包:

创建用于存储解码后的帧的AVFrame对象以及用于存储解码前的数据包的AVPacket对象。

AVFrame *pFrame = av_frame_alloc();
AVPacket *pPacket = av_packet_alloc();

7.解码:

使用循环读取每个数据包,将数据包发送到解码器进行解码,得到解码后的帧。

while (av_read_frame(pFormatCtx, pPacket) >= 0) {
    if (pPacket->stream_index == videoStreamIndex) {
        avcodec_receive_frame(pCodecCtx, pFrame);
        // 处理解码后的帧(显示、保存等)
    }
    av_packet_unref(pPacket);
}

8.释放资源

avformat_close_input(&pFormatCtx);
avcodec_free_context(&pCodecCtx);
av_frame_free(&pFrame);
av_packet_free(&pPacket);

使用ffmpeg解码视频文件

本例子使用FFmpeg库解码视频文件,并将解码后的帧保存为PPM图像文件。文章来源地址https://www.toymoban.com/news/detail-819660.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>

#define IN_FILE_PATH "input_video.mp4"
#define OUT_FILE_PATH "output_frame.ppm"

int main() {
    AVFormatContext *pFormatCtx = NULL;
    AVCodecContext *pCodecCtx = NULL;
    AVCodec *pCodec = NULL;
    AVFrame *pFrame = NULL;
    AVPacket packet;
    struct SwsContext *pSwsCtx = NULL;

    // Register all formats and codecs
    av_register_all();

    // Open input file
    if (avformat_open_input(&pFormatCtx, IN_FILE_PATH, NULL, NULL) != 0) {
        fprintf(stderr, "Could not open input file\n");
        return -1;
    }

    // Retrieve stream information
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        fprintf(stderr, "Could not find stream information\n");
        return -1;
    }

    // Find the first video stream
    int videoStream = -1;
    for (int i = 0; i < pFormatCtx->nb_streams; i++) {
        if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStream = i;
            break;
        }
    }

    if (videoStream == -1) {
        fprintf(stderr, "Could not find a video stream\n");
        return -1;
    }

    // Get a pointer to the codec context for the video stream
    pCodec = avcodec_find_decoder(pFormatCtx->streams[videoStream]->codecpar->codec_id);
    if (pCodec == NULL) {
        fprintf(stderr, "Unsupported codec\n");
        return -1;
    }

    pCodecCtx = avcodec_alloc_context3(pCodec);
    if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar) < 0) {
        fprintf(stderr, "Failed to copy codec parameters to codec context\n");
        return -1;
    }

    // Open codec
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        return -1;
    }

    // Allocate video frame
    pFrame = av_frame_alloc();

    // Setup scaler context to convert video frames to RGB
    pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                             pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24,
                             SWS_BILINEAR, NULL, NULL, NULL);

    if (pSwsCtx == NULL) {
        fprintf(stderr, "Failed to allocate SwsContext\n");
        return -1;
    }

    // Open output file for writing PPM
    FILE *ppmFile = fopen(OUT_FILE_PATH, "wb");
    if (ppmFile == NULL) {
        fprintf(stderr, "Could not open output file\n");
        return -1;
    }

    // Read frames and save as PPM
    while (av_read_frame(pFormatCtx, &packet) >= 0) {
        if (packet.stream_index == videoStream) {
            // Decode video frame
            int response = avcodec_send_packet(pCodecCtx, &packet);
            if (response < 0) {
                fprintf(stderr, "Error decoding frame (avcodec_send_packet)\n");
                break;
            }

            while (response >= 0) {
                response = avcodec_receive_frame(pCodecCtx, pFrame);
                if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
                    break;
                } else if (response < 0) {
                    fprintf(stderr, "Error decoding frame (avcodec_receive_frame)\n");
                    break;
                }

                // Convert the frame to RGB
                uint8_t *buffer = NULL;
                int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
                buffer = av_malloc(numBytes * sizeof(uint8_t));

                av_image_fill_arrays(pFrame->data, pFrame->linesize, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);

                sws_scale(pSwsCtx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrame->data, pFrame->linesize);

                // Save the frame as PPM
                fprintf(ppmFile, "P6\n%d %d\n255\n", pCodecCtx->width, pCodecCtx->height);
                fwrite(buffer, 1, numBytes, ppmFile);

                av_free(buffer);
            }
        }

        av_packet_unref(&packet);
    }

    // Clean up
    av_frame_free(&pFrame);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
    sws_freeContext(pSwsCtx);
    fclose(ppmFile);

    return 0;
}

到了这里,关于ffmpeg实现视频解码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【配置环境】安装Ffmpeg音视频编解码工具和搭建EasyDarwin开源流媒体服务器

    目录 一,安装Ffmpeg音视频编解码工具 1,简介 2,开发文档 3,安装部署 二,搭建EasyDarwin开源流媒体服务器 1,简介 2,主要功能特点 3,安装部署 4,效果图 三,简单测试 Ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许

    2024年02月07日
    浏览(78)
  • FFmpeg源码分析:avcodec_send_packet()与avcodec_receive_frame()音视频解码

    FFmpeg在libavcodec模块,旧版本提供avcodec_decode_video2()作为视频解码函数,avcodec_decode_audio4()作为音频解码函数。在FFmpeg 3.1版本新增avcodec_send_packet()与avcodec_receive_frame()作为音视频解码函数。后来,在3.4版本把avcodec_decode_video2()和avcodec_decode_audio4()标记为过时API。版本变更描述如下

    2024年02月03日
    浏览(53)
  • FFmpeg 音视频开发工具

    目录 FFmpeg 下载与安装 ffmpeg 使用快速入门 ffplay 使用快速入门 1、FFmpeg 是处理音频、视频、字幕和相关元数据等多媒体内容的库和工具的集合。一个完整的跨平台解决方案,用于录制、转换和流式传输音频和视频。 官网:https://www.ffmpeg.org/ 源码:https://github.com/FFmpeg/FFmpeg。

    2024年02月15日
    浏览(54)
  • 音视频开发-ffmpeg介绍-系列一

    目录 一.简介 FFmpeg框架的基本组成包含: 二. FFmpeg框架梳理音视频的流程​编辑 基本概念: 三.ffmpeg、ffplay、ffprobe区别      4.1 ffmpeg是用于转码的应用程序  4.2 fffplay是用于播放的应用程序       4.3 ffprobe是用于查看文件格式的应用程序      4.4 ffmpeg是用于转码的应用程

    2024年02月16日
    浏览(44)
  • 音视频开发---ffmpeg rtmp推流

    推流是将输入视频数据推送至流媒体服务器, 输入视频数据可以是本地视频文件(avi,mp4,flv......),也可以是内存视频数据,或者摄像头等系统设备,也可以是网络流URL。本篇介绍将本地视频文件通过FFmpeg编程以RTMP直播流的形式推送至RTMP流媒体服务器的方法。 推流的网络拓扑

    2024年02月16日
    浏览(79)
  • 玩赚音视频开发高阶技术——FFmpeg

    随着移动互联网的普及,人们对音视频内容的需求也不断增加。无论是社交媒体平台、电商平台还是在线教育,都离不开音视频的应用。这就为音视频开发人员提供了广阔的就业机会。根据这些年来网站上的音视频开发招聘需求来看,音视频开发人员的需求量大,且薪资待遇

    2024年02月13日
    浏览(64)
  • Qt音视频开发38-ffmpeg视频暂停录制的设计

    基本上各种播放器提供的录制视频接口,都是只有开始录制和结束录制两个,当然一般用的最多的也是这两个接口,但是实际使用过程中,还有一种可能需要中途暂停录制,暂停以后再次继续录制,将中间部分视频不需要录制,跳过这部分不需要的视频,而且录制的视频文件

    2023年04月20日
    浏览(72)
  • Android 音视频开发实践系列-06-初步了解H.264视频编解码技术标准

    本文来自笔者本人的语雀博客,由于语雀升级后不再满足笔者的需求,因此之后笔者会陆续将一些之前已经发布但尚有价值的文章搬家到CSDN。 作为音视频行业从业者,怎么能不理解H.264视频编解码技术标准?本篇文章主要记录笔者学习过程中对众多优秀博客内容的摘抄整理,

    2023年04月09日
    浏览(51)
  • 音视频处理 ffmpeg中级开发 H264编码

    libavcodec/avcodec.h 常用的数据结构 AVCodec 编码器结构体 AVCodecContext 编码器上下文 AVFrame 解码后的帧 结构体内存的分配和释放 av_frame_alloc 申请 av_frame_free() 释放 avcodec_alloc_context3() 创建编码器上下文 avcodec_free_context() 释放编码器上下文 解码步骤 avcodec_find_decoder 查找解码器 avcod

    2024年02月01日
    浏览(82)
  • 音视频开发实战03-FFmpeg命令行工具移植

    作为一个音视频开发者,在日常工作中经常会使用ffmpeg 命令来做很多事比如转码 ffmpeg -y -i test.mov -g 150 -s 1280x720 -codec libx265 -r 25 test_h265.mp4 ,水平翻转视频: ffmpeg -i src.mp4 -vf hflip -acodec copy -vcodec h264 -b 22000000 out.mp4 ,视频截取: ffmpeg -i input.wmv -ss 00:00:30.0 -c copy -t 00:00:10.0 ou

    2024年02月16日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包