AVI转MP4 Linux ffmpeg

本文详细介绍了使用FFmpeg进行视频解码和编码的全过程,包括从AVI文件中解码视频帧并保存为YUV格式,再将YUV格式的视频重新编码为MP4格式。通过具体代码示例,深入解析了FFmpeg库的使用方法,如avformat、avcodec、avdevice和swscale等模块的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

extern "C"
{
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavcodec/avcodec.h"
};
int pNewWidth = 0;
int pNewHeight = 0;
#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
#define AVFMT_RAWPICTURE 0x0020


void SetVideoFrame(AVCodecContext *pCodecCtx, AVFrame *pFrame, AVFrame *pNewFrame, int pNewWidth, int pNewHeight)
{
    pNewFrame->linesize[0] = pNewWidth;
    pNewFrame->linesize[1] = pNewWidth / 2;
    pNewFrame->linesize[2] = pNewWidth / 2;
    struct SwsContext *pSwsCtx = NULL;
    pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_BGR24, pNewWidth, pNewHeight, AV_PIX_FMT_BGR24, SWS_SINC, NULL, NULL, NULL);
    if (pSwsCtx == NULL)
        return;
    sws_scale(pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pNewFrame->data, pNewFrame->linesize);
    sws_freeContext(pSwsCtx);
}

int VideoDecode(char *VideoName, char* YUVName)
{
    FILE *fw = fopen(YUVName, "wb");
    if (fw == NULL)
        return -1;
    AVFormatContext *pFormatContext = NULL;
    pFormatContext = avformat_alloc_context();
    if (avformat_open_input(&pFormatContext, VideoName, NULL, NULL) != 0)
        return -2;
    if (avformat_find_stream_info(pFormatContext, NULL) < 0)
    {
        avformat_close_input(&pFormatContext);
        return -3;
    }
    AVCodecContext *pCodecContext = NULL;
    pCodecContext = pFormatContext->streams[0]->codec;
    AVCodec *pCodec = NULL;
    pCodec = avcodec_find_decoder(pCodecContext->codec_id);
    if (pCodec == NULL)
    {
        avformat_close_input(&pFormatContext);
        return -4;
    }
    if (avcodec_open2(pCodecContext, pCodec, NULL) < 0)
    {
        avformat_close_input(&pFormatContext);
        return -5;
    }
    AVFrame *pFrame, *pFrameDispose;
    pFrame = av_frame_alloc();
    pFrameDispose = av_frame_alloc();
    if ((pFrame == NULL) || (pFrameDispose == NULL))
    {
        avcodec_close(pCodecContext);
        avformat_close_input(&pFormatContext);
        return -6;
    }

    pNewWidth = pCodecContext->width;
    pNewHeight = pCodecContext->height;

    int DisposeSize = avpicture_get_size(AV_PIX_FMT_BGR24, pCodecContext->width, pCodecContext->height);
    uint8_t *DisposeBuf = (uint8_t *)av_malloc(DisposeSize*sizeof(uint8_t));
    avpicture_fill((AVPicture *)pFrameDispose, DisposeBuf, AV_PIX_FMT_BGR24, pCodecContext->width, pCodecContext->height);
    AVPacket pPacket;
    int got_picture_ptr = 0;
    while (av_read_frame(pFormatContext, &pPacket) >= 0)
    {
        if (pPacket.stream_index == 0)
        {
            if (avcodec_decode_video2(pCodecContext, pFrame, &got_picture_ptr, &pPacket) >= 0)
            {
                if (got_picture_ptr)
                {
                    SetVideoFrame(pCodecContext, pFrame, pFrameDispose, pCodecContext->width, pCodecContext->height);
                    fwrite(DisposeBuf, 1, DisposeSize, fw);
                }
            }
        }
    }
    fclose(fw);
    av_free(DisposeBuf);
    av_frame_free(&pFrameDispose);
    av_frame_free(&pFrame);
    avcodec_close(pCodecContext);
    avformat_close_input(&pFormatContext);
    return 0;
}

int yuv420p_to_mp4(char* yuv420p_name, char* mp4_name)
{
    FILE* fr_yuv420p = fopen(yuv420p_name, "rb");
    if (fr_yuv420p == NULL)
        return -1;

    AVOutputFormat* pOutputFormat = av_guess_format(NULL, mp4_name, NULL);
    AVPacket *avpacket;
    if (pOutputFormat == NULL)
    {
        fclose(fr_yuv420p);
        return -2;
    }
    AVFormatContext* pFormatContext = avformat_alloc_context();
    if (pFormatContext == NULL)
    {
        fclose(fr_yuv420p);
        return -3;
    }
    pFormatContext->oformat = pOutputFormat;
    strncpy(pFormatContext->filename, mp4_name, sizeof(pFormatContext->filename));
    if (pOutputFormat->video_codec == AV_CODEC_ID_NONE)
    {
        avformat_free_context(pFormatContext);
        fclose(fr_yuv420p);
        return -4;
    }

    AVStream* pStream = avformat_new_stream(pFormatContext, NULL);
    if (pStream == NULL)
    {
        avformat_free_context(pFormatContext);
        fclose(fr_yuv420p);
        return -5;
    }
    AVCodecContext* pCodecContext = pStream->codec;
    pCodecContext->codec_id = pFormatContext->oformat->video_codec;
    pCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
    pCodecContext->bit_rate = 400000;
    pCodecContext->gop_size = 3;
    pCodecContext->pix_fmt = AV_PIX_FMT_BGR24;
    pCodecContext->width = pNewWidth;
    pCodecContext->height = pNewHeight;
    pCodecContext->time_base.num = 1;
    pCodecContext->time_base.den = 10;
    pCodecContext->me_range = 16;
    pCodecContext->max_qdiff = 4;
    pCodecContext->qcompress = 0.6;
    if (pCodecContext->codec_id == AV_CODEC_ID_MPEG2VIDEO)
        pCodecContext->max_b_frames = 2;
    if (pCodecContext->codec_id == AV_CODEC_ID_MPEG1VIDEO)
        pCodecContext->mb_decision = 2;
    if (!strcmp(pFormatContext->oformat->name, "mp4") || !strcmp(pFormatContext->oformat->name, "mov") || !strcmp(pFormatContext->oformat->name, "3gp"))
        pCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

    AVCodec* pCodec = avcodec_find_encoder(pCodecContext->codec_id);
    if (avcodec_open2(pCodecContext, pCodec, NULL) < 0)
    {
        avformat_free_context(pFormatContext);
        fclose(fr_yuv420p);
        return -6;
    }

    if (avio_open(&pFormatContext->pb, mp4_name, AVIO_FLAG_WRITE) < 0)
    {
        avcodec_close(pCodecContext);
        avformat_free_context(pFormatContext);
        fclose(fr_yuv420p);
        return -7;
    }

    int *video_outbuf_size;;
    uint8_t* video_outbuf = NULL;
    if (!(pFormatContext->oformat->flags & AVFMT_RAWPICTURE))
    {
        video_outbuf_size = 200000;
        video_outbuf = (uint8_t*)av_malloc(video_outbuf_size);
    }

    int pFrameSize = avpicture_get_size(pCodecContext->pix_fmt, pCodecContext->width, pCodecContext->height);
    uint8_t* pFrameBuf = (uint8_t*)av_malloc(pFrameSize);
    AVFrame* pFrame = av_frame_alloc();
    if (pFrame == NULL)
    {
        avio_close(pFormatContext->pb);
        avcodec_close(pCodecContext);
        avformat_free_context(pFormatContext);
        fclose(fr_yuv420p);
        return -8;
    }
    avpicture_fill((AVPicture *)pFrame, pFrameBuf, pCodecContext->pix_fmt, pCodecContext->width, pCodecContext->height);
    pFrame->format = pCodecContext->pix_fmt;
    pFrame->width = pCodecContext->width;
    pFrame->height = pCodecContext->height;

    if (avformat_write_header(pFormatContext, NULL) < 0)
    {
        av_free(pFrame);
        av_free(pFrameBuf);
        avio_close(pFormatContext->pb);
        avcodec_close(pCodecContext);
        avformat_free_context(pFormatContext);
        fclose(fr_yuv420p);
        return -9;
    }

    while (1)
    {
        if (fread(pFrame->data[0], 1, pFrameSize, fr_yuv420p) != pFrameSize)
            break;

        pFrame->pts++;

        int ReturnValue = 0, buf_size = 0;
        AVPacket pPacket;
        if (pFormatContext->oformat->flags & AVFMT_RAWPICTURE)
        {
            av_init_packet(&pPacket);
            pPacket.flags |= AV_PKT_FLAG_KEY;
            pPacket.stream_index = pStream->index;
            pPacket.data = (uint8_t*)pFrame;
            pPacket.size = sizeof(AVPicture);
            ReturnValue = av_write_frame(pFormatContext, &pPacket);
        }
        else
        {
            buf_size = avcodec_encode_video2(pCodecContext, avpacket,pFrame,video_outbuf_size);
            if (buf_size > 0)
            {
                av_init_packet(&pPacket);
                if (pCodecContext->coded_frame->key_frame)
                    pPacket.flags |= AV_PKT_FLAG_KEY;
                pPacket.stream_index = pStream->index;
                pPacket.data = video_outbuf;
                pPacket.size = buf_size;
                ReturnValue = av_write_frame(pFormatContext, &pPacket);
            }
            else
                ReturnValue = 0;
        }
        if (ReturnValue != 0)
        {
            av_free_packet(&pPacket);
            av_free(pFrame);
            av_free(pFrameBuf);
            avio_close(pFormatContext->pb);
            avcodec_close(pCodecContext);
            avformat_free_context(pFormatContext);
            fclose(fr_yuv420p);
            return -10;
        }
    }

    av_write_trailer(pFormatContext);

    av_free(pFrame);
    av_free(pFrameBuf);
    avio_close(pFormatContext->pb);
    avcodec_close(pCodecContext);
    avformat_free_context(pFormatContext);
    fclose(fr_yuv420p);
    return 0;
}*/

int main()
{
    av_register_all();
    if (VideoDecode("1.avi", "20170105.yuv") != 0)
        printf("VideoDecode fail\n");
    //if (yuv420p_to_mp4("20170105.yuv", "20170105.mp4") != 0)
        //printf("yuv420p_to_mp4 fail\n");
    return 0;
}
 

 

g++ pcm2aacts2mp4.cpp -o pcm2aacaaaaaa -L/usr/local/lib -lfaac -I/usr/local/include -I/monchickey/ffmpeg/include -L/monchickey/ffmpeg/lib -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil
 ———————————————— 
版权声明:本文为CSDN博主「天巽夕」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/aa804738534/article/details/99598105

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寰宇C++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值