欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MP4转YUV

程序员文章站 2022-07-13 12:50:13
...
  • 代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavformat/avfrmat.h>
const char* SRC_FILE = "1.mp4";

int main()
{
    FILE *yuv_file = fopen("yuv_file","ab");
    if (!yuv_file)
        return 0;
    av_register_all();
    AVFormatContext* pFormat = NULL;
    if (avformat_open_input(&pFormat, SRC_FILE, NULL, NULL) < 0)
    {
        return 0;
    }
    AVCodecContext* video_dec_ctx = NULL;
    AVCodec* video_dec = NULL;
    if (avformat_find_stream_info(pFormat, NULL) < 0)
    {
        return 0;
    }
    av_dump_format(pFormat,0,SRC_FILE,0);
    video_dec_ctx = pFormat->streams[0]->codec;
    video_dec = avcodec_find_decoder(video_dec_ctx->codec_id);
    if (avcodec_open2(video_dec_ctx, video_dec, NULL) < 0)
    {
        return 0;
    }
    AVPacket *pkt = new AVPacket();
    av_init_packet(pkt);
    while (1)
    {
        if (av_read_frame(pFormat, pkt) < 0)
        {
            fclose(yuv_file);
            delete pkt;
            return 0;
        }
        if (pkt->stream_index == 0)
        {
           // AVFrame *pFrame = avcodec_alloc_frame();
            AVFrame *pFrame = av_frame_alloc();
            int got_picture = 0,ret = 0;
            ret = avcodec_decode_video2(video_dec_ctx, pFrame, &got_picture, pkt);
            if (ret < 0)
            {
                delete pkt;
                return 0;
            }
            if (got_picture)
            {
                char* buf = new char[video_dec_ctx->height * video_dec_ctx->width * 3 / 2];
                memset(buf, 0, video_dec_ctx->height * video_dec_ctx->width * 3 / 2);
                int height = video_dec_ctx->height;
                int width = video_dec_ctx->width;
                printf("decode video ok\n");
                int a = 0, i;
                for (i = 0; i<height; i++)
                {
                    memcpy(buf + a, pFrame->data[0] + i * pFrame->linesize[0], width);
                    a += width;
                }
                for (i = 0; i<height / 2; i++)
                {
                    memcpy(buf + a, pFrame->data[1] + i * pFrame->linesize[1], width / 2);
                    a += width / 2;
                }
                for (i = 0; i<height / 2; i++)
                {
                    memcpy(buf + a, pFrame->data[2] + i * pFrame->linesize[2], width / 2);
                    a += width / 2;
                }
                fwrite(buf, 1, video_dec_ctx->height * video_dec_ctx->width * 3 / 2, yuv_file);
                buf = NULL;
            }
            avcodec_free_frame(&pFrame);
        }
    }

    return 0;
}

编译出现如下:
MP4转YUV

  • 解决:
    在libavutil/common.h中添加
#ifndef UINT64_C(val)
#define UINT64_C(val) val##ULL
#endif

MP4转YUV
将 avcodec_alloc_frame() 替换为 av_frame_alloc()。
使用makefile工具
MP4转YUV
makefile如下:

#!/bin/bash

CC=gcc
CXX=g++
TARGET=mp4_TO_YUV
OBJS=mp4_TO_YUV.o
LDFLAGS+=-lavformat -lavcdec -lavfiler -lavdevice -lswscale -lavutil -ldl -lz -lpthread -lswresample

%.o: %.cpp
        $(CXX)  $(LDFAGS) -c $< -o aaa@qq.com

SOURCE = mp4_TO_YUV.cpp

$(TARGET):$(OBJS)
        $(CXX) $(OBJS) $(LDFLAGS) -o $(TARGET)

clean:
        rm -rf *.o mp4_TO_YUV

生成成功执行make
运行如下:
生成成功
执行后:
[aaa@qq.com test]# ./mp4_TO_YUV
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘1.mp4’:
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42isom
creation_time : 2016-09-10T01:13:22.000000Z
Duration: 00:04:19.18, start: 0.000000, bitrate: 2770 kb/s
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 96000 Hz, stereo, fltp, 127 kb/s (default)
Metadata:
creation_time : 2016-09-10T01:13:22.000000Z
handler_name : GPAC ISO Audio Handler
Stream #0:1(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x576 [SAR 1:1 DAR 20:9], 2635 kb/s, 25 fps, 25 tbr, 30k tbn, 20000k tbc (default)
Metadata:
creation_time : 2016-09-10T01:13:24.000000Z
handler_name : GPAC ISO Video Handler
[aac @ 0x269c700] Invalid media type for video