Macos arm64 ffmpeg h264 还原成yuv

首先编译 ffmpeg

  • 由于编译很多依赖尝试了三天果断放弃~
  • 使用brew
brew install  ffmpeg
brew info  ffmpeg

cmakelist.txt

cmake_minimum_required(VERSION 3.20)
project(ffmpeg_base C)
set(CMAKE_C_STANDARD 11)
set(FFMPEG_DIR /usr/local/Cellar/ffmpeg/6.1.1_3)
include_directories(${FFMPEG_DIR}/include/)
link_directories(${FFMPEG_DIR}/lib/)
add_executable(ffmpeg_base main.c)
target_link_libraries(ffmpeg_base
        swscale
        swresample
        avcodec
        avutil
        avdevice
        avfilter
        avformat
)

源码

#include <stdio.h>
#include <time.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>


#define IMAGE_WIDTH   1920
#define IMAGE_HEIGHT  1080
char* in_file = "/Users/jimogangdan/CLionProjects/x264_encoder/video1.h264";
char* out_file = "/Users/jimogangdan/CLionProjects/x264_encoder/video1.yuv";
void print_pict_type(int frame_cnt, AVFrame* pFrame);

// ffplay -video_size 1920x1080 -i video1.yuv
int main(int argc, char** argv)
{
    AVFormatContext* avFormatContext = avformat_alloc_context();
    if (avformat_open_input(&avFormatContext, in_file, NULL, NULL) != 0)
    {
        av_log(NULL, AV_LOG_ERROR, "can not open  input file \n");
        return -1;
    }

    if (avformat_find_stream_info(avFormatContext, NULL) < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "find stream error");
        return -1;
    }



    int videoIndex = -1;
    for (int i = 0; i < avFormatContext->nb_streams; i++)
    {
        if (AVMEDIA_TYPE_VIDEO == avFormatContext->streams[i]->codecpar->codec_type)
        {
            videoIndex = i;
            break;
        }
    }

    if (videoIndex == -1)
    {
        av_log(NULL, AV_LOG_ERROR, "not find a video stream");
        return -1;
    }

    const AVCodecParameters* codec_parameters = avFormatContext->streams[videoIndex]->codecpar;
    const AVCodec* pCodec = avcodec_find_decoder(codec_parameters->codec_id);
    if (!pCodec)
    {
        av_log(NULL, AV_LOG_ERROR, "Codec not found\n");
        return -1;
    }

    AVCodecContext* pCodecContext = avcodec_alloc_context3(pCodec);
    if (!pCodecContext)
    {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate video codec context\n");
        return -1;
    }

    const int openResult = avcodec_open2(pCodecContext, pCodec, NULL);
    if (openResult < 0)
    {
        av_log(NULL, AV_LOG_ERROR, "avcodec open2 result %d", openResult);
        return -1;
    }

    FILE* pYUVFile = fopen(out_file, "wb+");
    if (pYUVFile == NULL)
    {
        av_log(NULL, AV_LOG_ERROR, " fopen outPut file error");
        return -1;
    }

    AVPacket* packet = av_malloc(sizeof(AVPacket));
    AVFrame* pFrame = av_frame_alloc();
    AVFrame* pFrameYUV = av_frame_alloc();

    const uint8_t* out_buffer = (unsigned char*)av_malloc(
        av_image_get_buffer_size(
            AV_PIX_FMT_YUV420P,
            codec_parameters->width,
            codec_parameters->height,
            1
        )
    );

    av_image_fill_arrays(
        pFrameYUV->data,
        pFrameYUV->linesize,
        out_buffer,
        AV_PIX_FMT_YUV420P,
        codec_parameters->width,
        codec_parameters->height,
        1
    );

    struct SwsContext* img_convert_ctx = sws_getContext(
        codec_parameters->width,
        codec_parameters->height,
        codec_parameters->codec_type,
        codec_parameters->width,
        codec_parameters->height,
        AV_PIX_FMT_YUV420P,
        SWS_BICUBIC,
        NULL,
        NULL,
        NULL
    );

    int readPackCount = -1;
    int frame_cnt = 0;
    const clock_t start_time = clock();
    while ((readPackCount = av_read_frame(avFormatContext, packet) >= 0))
    {
        av_log(NULL, AV_LOG_INFO, " read fame count is %d\n", readPackCount);

        if (packet->stream_index == videoIndex)
        {
            const int sendPacket = avcodec_send_packet(pCodecContext, packet);
            if (sendPacket != 0)
            {
                av_log(NULL, AV_LOG_ERROR, "avodec send packet error %d\n", sendPacket);
                continue;
            }
            const int receiveFrame = avcodec_receive_frame(pCodecContext, pFrame);

            if (receiveFrame != 0)
            {
                av_log(NULL, AV_LOG_INFO, "avcodec_receive_frame is being  green ,dropped %d\n", receiveFrame);
                continue;
            }
            sws_scale(
                img_convert_ctx, (const uint8_t*const *)
                pFrame->data,
                pFrame->linesize,
                0,
                pCodecContext->height,
                pFrameYUV->data,
                pFrameYUV->linesize
            );

            const int y_size = codec_parameters->width * codec_parameters->height;
            fwrite(pFrameYUV->data[0], 1, y_size, pYUVFile); //Y
            fwrite(pFrameYUV->data[1], 1, y_size / 4, pYUVFile); //U
            fwrite(pFrameYUV->data[2], 1, y_size / 4, pYUVFile); //V

            print_pict_type(frame_cnt, pFrame);
            frame_cnt++;
        }
    }

    av_log(NULL, AV_LOG_INFO, "frame count is %d", frame_cnt);
    const clock_t end_time = clock();
    av_log(NULL, AV_LOG_INFO, "decode video use Time %ld", (end_time - start_time));

    av_packet_unref(packet);
    sws_freeContext(img_convert_ctx);
    fclose(pYUVFile);
    av_frame_free(&pFrameYUV);
    av_frame_free(&pFrame);
    avcodec_close(pCodecContext);
    avformat_close_input(&avFormatContext);

    return 0;
}

void print_pict_type(const int frame_cnt, const AVFrame* pFrame)
{
    char pictypeStr[10] = {0};
    switch (pFrame->pict_type)
    {
    case AV_PICTURE_TYPE_I:
        {
            sprintf(pictypeStr, "I");
            break;
        }
    case AV_PICTURE_TYPE_P:
        {
            sprintf(pictypeStr, "P");
            break;
        }
    case AV_PICTURE_TYPE_B:
        {
            sprintf(pictypeStr, "B");
            break;
        }
    default:
        break;
    }
    av_log(NULL, AV_LOG_INFO, "Frame index %5d. Tpye %s\n", frame_cnt, pictypeStr);
}

posted @ 2024-02-28 16:32  vx_guanchaoguo0  阅读(19)  评论(0编辑  收藏  举报