首页 > 其他分享 >ffmpeg保存视频为bmp图片

ffmpeg保存视频为bmp图片

时间:2024-05-28 23:11:37浏览次数:21  
标签:视频 return ffmpeg avcodec ret bmp codecCtx av NULL

方法1:命令保存

# 保存bmp图片
ffmpeg -i input.mp4 -vf scale=768:432 picture/%d.bmp
# 播放
ffplay picture/87.bmp

方法2:代码保存

 main.c

#include "libavutil/log.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libavutil/parseutils.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"

#define WORD uint16_t
#define DWORD uint32_t
#define LONG int32_t

#pragma pack(2)
typedef struct TagBitMapFileHeader {
    WORD bfType;
    DWORD bfSize;
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bfOffBits;
} BitMapFileHeader;

typedef struct TagBitMapInfoHeader {
    DWORD biSize;
    LONG biWidth;
    LONG biHeight;
    WORD biPlanes;
    WORD biBitCount;
    DWORD biCompression;
    DWORD biSizeImage;
    LONG biXPelsPerMeter;
    LONG biYPelsPerMeter;
    DWORD biClrUsed;
    DWORD biClrImportant;
} BitMapInfoHeader;

int frameCount = 0;

void saveBmp(const char *filename, unsigned char *rgbData, int width, int height) {
    int bmpDataSize = width * height * 3;
    BitMapFileHeader bitMapFileHeader = {0};
    bitMapFileHeader.bfType = 0x4d42;
    bitMapFileHeader.bfSize = sizeof(BitMapFileHeader) + sizeof(BitMapInfoHeader) + bmpDataSize;
    bitMapFileHeader.bfOffBits = sizeof(BitMapFileHeader) + sizeof(BitMapInfoHeader);

    BitMapInfoHeader bitMapInfoHeader = {0};
    bitMapInfoHeader.biSize = sizeof(BitMapInfoHeader);
    bitMapInfoHeader.biWidth = width;
    bitMapInfoHeader.biHeight = height * (-1);
    bitMapInfoHeader.biPlanes = 1;
    bitMapInfoHeader.biBitCount = 24;
    bitMapInfoHeader.biCompression = 0;
    bitMapInfoHeader.biSizeImage = 0;
    bitMapInfoHeader.biXPelsPerMeter = 0;
    bitMapInfoHeader.biYPelsPerMeter = 0;
    bitMapInfoHeader.biClrUsed = 0;
    bitMapInfoHeader.biClrImportant = 0;
    FILE *fp = fopen(filename, "wb");
    fwrite(&bitMapFileHeader, 1, sizeof(BitMapFileHeader), fp);
    fwrite(&bitMapInfoHeader, 1, sizeof(BitMapInfoHeader), fp);
    //    fwrite(rgbData, 1, bmpDataSize, fp);
    // BMP stores color data in BGR format, so we need to convert RGB to BGR
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            uint8_t r = rgbData[(y * width + x) * 3 + 0];
            uint8_t g = rgbData[(y * width + x) * 3 + 1];
            uint8_t b = rgbData[(y * width + x) * 3 + 2];
            fwrite(&b, 1, 1, fp);
            fwrite(&g, 1, 1, fp);
            fwrite(&r, 1, 1, fp);
        }
    }
    fclose(fp);

}


int decodeVideo(AVCodecContext *codecCtx, AVPacket *packet, struct SwsContext *c, int dstWeight, int dstHeight,
                AVFrame *dstFrame, FILE *dst) {
    int ret = avcodec_send_packet(codecCtx, packet);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_send_packet failed: %s\n", av_err2str(ret));
        av_packet_unref(packet);
        return ret;
    }
    AVFrame *frame = av_frame_alloc();
    while ((ret = avcodec_receive_frame(codecCtx, frame)) == 0) {
        sws_scale(c, (const uint8_t *const *) frame->data, frame->linesize, 0, codecCtx->height, dstFrame->data,
                  dstFrame->linesize);
        char bmpFilename[64] = {0};
        snprintf(bmpFilename, sizeof(bmpFilename), "../picture/%d.bmp", frameCount);
        saveBmp(bmpFilename, dstFrame->data[0], dstWeight, dstHeight);
        frameCount++;
    }
    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
        av_frame_free(&frame);
        return 0;
    } else if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_receive_frame failed: %s\n", av_err2str(ret));
        av_frame_free(&frame);
        return ret;
    }
    av_frame_free(&frame);
    return 0;
}

int main(int argc, char **argv) {
    av_log_set_level(AV_LOG_DEBUG);
    if (argc < 4) {
        av_log(NULL, AV_LOG_ERROR, "Usage: %s inputFile outputFile\n", argv[0]);
        return -1;
    }
    const char *inputFile = argv[1];
    const char *outputFile = argv[2];
    const char *dstVideoSizeString = argv[3];
    int ret;
    int dstHeight = 0;
    int dstWeight = 0;
    ret = av_parse_video_size(&dstWeight, &dstHeight, dstVideoSizeString);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "av_parse_video_size failed: %s\n", inputFile, av_err2str(ret));
        return -1;
    }
    AVFormatContext *fCtx = NULL;


    if ((ret = avformat_open_input(&fCtx, inputFile, NULL, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Open input file %s failed: %s\n", inputFile, av_err2str(ret));
        return -1;
    }
    if ((ret = avformat_find_stream_info(fCtx, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Find input file stream info failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        return -1;
    }

    ret = av_find_best_stream(fCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "av_find_best_stream failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        return -1;
    }
    int videoIndex = ret;

    AVCodecContext *codecCtx = avcodec_alloc_context3(NULL);
    if (codecCtx == NULL) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_alloc_context3 failed\n");
        avformat_close_input(&fCtx);
        return -1;
    }
    if ((ret = avcodec_parameters_to_context(codecCtx, fCtx->streams[videoIndex]->codecpar)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_parameters_to_context failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }

    AVCodec *decoder = avcodec_find_decoder(codecCtx->codec_id);
    if (decoder == NULL) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_find_decoder failed\n");
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }
    if ((ret = avcodec_open2(codecCtx, decoder, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "avcodec_open2 failed: %s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }
    enum AVPixelFormat dstFormat = AV_PIX_FMT_RGB24;
    struct SwsContext *swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
                                               dstWeight, dstHeight, dstFormat,
                                               SWS_FAST_BILINEAR, NULL, NULL, NULL);
    if (swsCtx == NULL) {
        av_log(NULL, AV_LOG_ERROR, "sws_getContext failed\n");
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }
    AVFrame *dstFrame = av_frame_alloc();
    ret = av_image_get_buffer_size(dstFormat, dstWeight, dstHeight, 1);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "av_image_get_buffer_size failed:%s\n", av_err2str(ret));
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }
    uint8_t *outBuffer = av_malloc(ret);
    av_image_fill_arrays(dstFrame->data, dstFrame->linesize, outBuffer, dstFormat, dstWeight, dstHeight, 1);
    FILE *dst = fopen(outputFile, "wb");
    if (dst == NULL) {
        av_log(NULL, AV_LOG_ERROR, "open outputFile failed\n");
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        return -1;
    }

    AVPacket *packet = av_packet_alloc();
    if (!packet) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate AVPacket\n");
        avformat_close_input(&fCtx);
        avcodec_free_context(&codecCtx);
        fclose(dst);
        return -1;
    }

    while (av_read_frame(fCtx, packet) == 0) {
        if (packet->stream_index == videoIndex) {
            if (decodeVideo(codecCtx, packet, swsCtx, dstWeight, dstHeight, dstFrame, dst) < 0) {
                av_packet_unref(packet);
                break;
            }
        }
        av_packet_unref(packet);
    }
    decodeVideo(codecCtx, NULL, swsCtx, dstWeight, dstHeight, dstFrame, dst);

    // Cleanup
    av_packet_free(&packet);
    avformat_close_input(&fCtx);
    avcodec_free_context(&codecCtx);
    fclose(dst);
    av_frame_free(&dstFrame);
    return 0;
}

Makefile

TARGET=main
SRC=main.c
CC=gcc
CFLAGS=-I /usr/local/ffmpeg/include
LDFLAGS=-L /usr/local/ffmpeg/lib
LDFLAGS+= -lavutil -lavformat -lavcodec -lswscale
all:$(TARGET)
$(TARGET):$(SRC)
    $(CC) $(SRC) $(CFLAGS) $(LDFLAGS) -o $(TARGET)
clean:
    rm -rf $(TARGET)

  

标签:视频,return,ffmpeg,avcodec,ret,bmp,codecCtx,av,NULL
From: https://www.cnblogs.com/navysummer/p/18219172

相关文章

  • 磁盘管理与文件系统视频
    目录命令创建分区分区方式(类型)磁盘标签类型:dos:MBR(主引导记录)分区类型磁盘标签类型:gbt:gbt(全局分区表)分区类型更改磁盘标签类型字节大小扇区格式化格式化命令挂载设置永久挂载转换分区类型硬盘:机械硬盘:盘片、主轴点机、磁头、传动手臂、电路板、电源接口、......
  • 智影AI故事转视频创作神器!快速开启AI绘画小说推文之旅
    1.前言1.1生成内容形式    生成内容形式主要包含三种,PGC(ProfessionallyGeneratedContent)、UGC(UserGeneratedContent)、AIGC(ArtificiallyIntelligentGeneratedContent)。也可以简单理解为生成内容形式的三个发展阶段。PGC专业生成内容    专业生成内容是由专......
  • ffmpeg修改颜色空间
    方法1:命令修改颜色空间#修改颜色空间ffmpeg-iinput.mp4-s1280*1024-pix_fmtrgb24output.rgb#播放ffplay-s1280*1024-pix_fmtrgb24output.rgb方法2:代码转换 main.c#include"libavutil/log.h"#include"libavformat/avformat.h"#include"libav......
  • 如何使用ChatGPT撰写短视频爆款文案
    在这个快速发展的数字时代,短视频已经成为最受欢迎的娱乐和信息获取方式之一。对于内容创作者来说,如何制作出爆款短视频,吸引更多观众的注意力,是他们面临的一大挑战。文案,作为视频内容的灵魂,起着至关重要的作用。那么,有没有什么工具能够帮助创作者高效地产出引人入胜的文案呢?答案......
  • OpenAI用26分钟改变世界!免费版GPT-4震撼登场,视频语音交互迈向科幻片级别
    一场长达26分钟的发布会,再次掀起了AI行业的风浪,将深刻改变我们未来的生活,也将让无数AI初创公司感到焦虑不安。这并非标题党,因为这次发布会由OpenAI主办。就在刚刚,OpenAI正式发布了GPT-4o。这个“o”代表“omni”,即全面、全能的意思。这一模型不仅拥有文本处理能力,还能处理图......
  • Nginx(openresty) 通过lua结合Web前端 实现图片,文件,视频等静态资源 访问权限验证,进行
    1本文系统环境:安装openresty(nginx),可参考:test@ubuntuserver:~$cat/etc/os-releasePRETTY_NAME="Ubuntu24.04LTS"NAME="Ubuntu"VERSION_ID="24.04"VERSION="24.04LTS(NobleNumbat)"VERSION_CODENAME=nobleID=ubuntuID_LIK......
  • 顶刊IJCV 2024 | EfficientSCI++:高效的视频单曝光压缩成像重建框架
    前言 来自浙江大学和西湖大学的研究人员提出了一种基于CNN-Transformer架构的高效、大尺度视频单曝光压缩成像重建算法EfficientSCI++。欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结、最新技术跟踪、经典论文解读、CV招聘信息。本文转载自PaperWeekly仅用于学术分......
  • 陪玩系统音频社交系统语音直播系统短视频系统陪玩陪玩系统程序陪玩系统搭建陪玩源码开
    在当今的科技世界中,游戏已经成为了人们日常生活的一部分。随着移动设备的普及和网络的发展,各种类型的游戏应运而生,满足了不同人群的需求。然而,有一种新兴的游戏模式正在逐渐受到玩家们的欢迎,那就是“陪玩”系统。那么,什么是陪玩系统开发呢?本文将对此进行详细的探讨。一、陪玩......
  • 【CV】视频图像背景分割MOG2,KNN,GMG
    当涉及背景分割器(BackgroundSubtractor)时,MixtureofGaussians(MOG2)、K-NearestNeighbors(KNN)和GeometricMultigid(GMG)是常用的算法。它们都用于从视频流中提取前景目标,并在计算机视觉和图像处理任务中发挥重要作用。MixtureofGaussians(MOG2):MOG2是一种基于高斯混合......
  • ffmpeg修改分辨率
    方法1:命令修改分辨率#修改分辨率ffmpeg-iinput.mp4-vfscale=1280:1024-frawvideooutput.yuv#播放ffplay-s1280*1024-pix_fmtyuv420poutput.yuv方法2:代码转换 main.c#include"libavutil/log.h"#include"libavformat/avformat.h"#include"l......