输出AAC声音目前有点问题:
输出YUV420 很好
[root@localhost 04]# cat main.c
#include <stdio.h>
#include "libavformat/avformat.h"
int frame_width = 0;
int frame_height = 0;
const char *src_filename = NULL;
const char *video_filename = NULL;
const char *audio_filename = NULL;
unsigned char *video_dst_data[4];
int video_dst_linesize[4];
int video_dst_buffersize;
enum AVPixelFormat pix_fmt;
//tmp var
AVFormatContext *fmt_ctx = NULL;
AVStream *pStream = NULL;
AVCodec *pcodec = NULL;
AVCodecContext *pCodecContext = NULL;
//video & audio var
AVStream *pVideoStream = NULL;
AVStream *pAudioStream = NULL;
AVCodecContext *pVideoCodecContext = NULL;
AVCodecContext *pAudioCodecContext = NULL;
FILE *pFilein = NULL;
FILE *pFileVideoOut = NULL;
FILE *pFileAudioOut = NULL;
AVFrame *frame = NULL;
AVPacket packet;
static int open_codec_context(enum AVMediaType type)
{
int ret = 0;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if(ret < 0)
{
printf("av_find_best_stream fail [%d]\n", ret);
return -1;
}
printf("av_find_best_stream OK [%d] \n", ret);
pStream = fmt_ctx->streams[ret];
pCodecContext = pStream->codec;
pcodec = avcodec_find_decoder(pCodecContext->codec_id);
if(NULL == pcodec)
{
printf("avcodec_find_decoder error \n");
return -1;
}
ret = avcodec_open2(pCodecContext, pcodec, NULL);
if(ret < 0)
{
printf("avcodec_open2 error [%d]", ret);
return -1;
}
}
static int decode_packet(int *got_frame)
{
int ret = 0 ;
if(packet.stream_index == pVideoStream->index)
{
//该packet属于视频
ret = avcodec_decode_video2(pVideoCodecContext, frame, got_frame, &packet);
printf("deal audio packet size=[%d], ", packet.size);
if(ret < 0)
{
printf("Error: decodec video frame \n");
return -1;
}
if(*got_frame)
{
printf("got audio frame, packet size=[%d]\n", packet.size);
av_image_copy(video_dst_data, video_dst_linesize,
(const char **)frame->data, frame->linesize,
pix_fmt,
frame_width, frame_height);
fwrite(video_dst_data[0],1, video_dst_buffersize, pFileVideoOut);
}
}
else if(packet.stream_index == pAudioStream->index)
{
//该packet属于音频
ret = avcodec_decode_audio4(pAudioCodecContext, frame, got_frame, &packet);
printf("deal audio packet size=[%d], ", packet.size);
if(ret < 0)
{
printf("Error: decodec audio frame \n");
return -1;
}
if(*got_frame)
{
printf("got video frame, packet size=[%d]\n", packet.size);
size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format);
fwrite(frame->extended_data[0], 1, unpadded_linesize, pFileAudioOut);
}
}
else
{
printf("unknow stream \n");
exit(0);
}
return packet.size;
}
int main(int argc, char **argv)
{
int ret = 0;
if(argc == 4)
{
src_filename = argv[1];
video_filename = argv[2];
audio_filename = argv[3];
printf("parameter OK \n");
printf("src_filename:[%s] \n", src_filename);
printf("video_filename:[%s] \n", video_filename);
printf("audio_filename:[%s] \n", audio_filename);
}
else
{
printf("parameter ERROR: \n");
return -1;
}
//加载编解码器
av_register_all();
//根据输入的视频文件初始化 AVFormatContext
ret = avformat_open_input(&fmt_ctx, src_filename, NULL, NULL);
if(ret < 0)
{
printf("ERROR avformat_open_input fail [%d] \n", ret);
return -1;
}
printf("avformat_open_input OK [%d] \n", ret);
//根据视频信息,查找解码器
ret = avformat_find_stream_info(fmt_ctx, NULL);
if(ret < 0)
{
printf("ERROR avformat_find_stream_info [%d]\n", ret);
return -1;
}
printf("avformat_find_stream_info OK [%d] \n", ret);
//打开视频
ret = open_codec_context(AVMEDIA_TYPE_VIDEO);
if(ret < 0)
{
printf("open_codec_context ERROR [%d]", ret);
return -1;
}
pVideoStream = pStream;
pVideoCodecContext = pCodecContext;
frame_width = pVideoCodecContext->width;
frame_height = pVideoCodecContext->height;
pix_fmt = pVideoCodecContext->pix_fmt;
printf("frame_width=[%d] \n", frame_width);
printf("frame_height=[%d] \n", frame_height);
ret = av_image_alloc(video_dst_data, video_dst_linesize, frame_width, frame_height, pix_fmt, 1);
if(ret < 0)
{
printf("av_image_alloc error [%d] \n", ret);
return -1;
}
printf("av_image_alloc buffersize=[%d] \n", ret);
video_dst_buffersize = ret;
pFileVideoOut = fopen(video_filename, "wb");
if(NULL == pFileVideoOut)
{
printf("foopen video_filename ERROR\n");
return -1;
}
// 打开音频
ret = open_codec_context(AVMEDIA_TYPE_AUDIO);
if(ret < 0)
{
printf("open_codec_context Audio ERROR [%d]", ret);
return -1;
}
pAudioStream = pStream;
pAudioCodecContext = pCodecContext;
pFileAudioOut = fopen(audio_filename, "wb");
if(NULL == pFileAudioOut)
{
printf("foopen audio_filename ERROR\n");
return -1;
}
av_dump_format(fmt_ctx, 0, src_filename, 0);//输出信息
//读取和处理音视频数据
frame = av_frame_alloc();
if(NULL == frame)
{
printf("av_frame_alloc error \n");
return -1;
}
printf("av_frame_alloc OK \n");
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0 ;
int get_frame_flags;
while(av_read_frame(fmt_ctx, &packet) >= 0)//从文件中读取出1帧
{
while(packet.size > 0)
{
ret = decode_packet(&get_frame_flags);
packet.data += ret;
packet.size -= ret;
}
}
//处理缓存区的数据
packet.data = NULL;
packet.size = 0;
while(get_frame_flags)
{
ret = decode_packet(&get_frame_flags);
packet.data += ret;
packet.size -= ret;
}
//收尾工作
avcodec_close(pVideoCodecContext);
avcodec_close(pAudioCodecContext);
avformat_close_input(&fmt_ctx);
av_frame_free(&frame);
av_free(video_dst_data[0]);
fclose(pFilein);
fclose(pFileVideoOut);
fclose(pFileAudioOut);
return 0;
}
[root@localhost 04]#Makefile 与使用方法:
[root@localhost 04]# cat makefile
FLAGS = -g
INCLUDEPATH = -I /home/ffmpeg_dev/include/
LIBPATH = -L /home/ffmpeg_dev/lib/
LIBS= -l avcodec -l pthread -l avutil -l m -l dl -l swresample -l avformat
exe=test
$(exe):
gcc main.c ${FLAGS} ${INCLUDEPATH} ${LIBPATH} ${LIBS} -o $@
clean:
rm -rf ${exe}
[root@localhost 04]#
[root@localhost 04]# cat auto.sh
clear
make clean
make
./test in.mp4 out.yuv out.aac
[root@localhost 04]#本文出自 “李春利” 博客,转载请与作者联系!
原文:http://990487026.blog.51cto.com/10133282/1977276