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);
}
本文来自博客园,作者:vx_guanchaoguo0,转载请注明原文链接:https://www.cnblogs.com/guanchaoguo/p/18040931