您的位置:首页 > 编程语言

ffmpeg-3.1.5视频+音频解码代码

2016-11-06 21:55 375 查看
之前文章中的代码只能解码视频数据,本文在之前的基础上加入了解码音频数据部分。

与之前只能解码视频的代码相比,本文代码增加了audioCodecCtx和audioCodec的处理部分、循环解码音频流的部分、和音频输出文件的设置部分。

解码后的音频为PCM格式,可以使用“audacity”软件进行分析。需要注意的是,在使用“audacity”软件分析PCM码流时,要通过“文件->导入->裸数据”的方法导入.pcm文件,而不要使用“文件->打开”的方式打开该文件。

上代码。

#include <stdio.h>
extern "C"
{
#include "include\libavcodec\avcodec.h"
#include "include\libavformat\avformat.h"
#include "include\libavutil\imgutils.h"
};

#define __STDC_CONSTANT_MACROS

int _tmain(int argc, _TCHAR* argv[])
{
//printf("%s", avcodec_configuration());
AVFormatContext *formatctx;
AVCodec *videoCodec;
AVCodec *audioCodec;
AVCodecContext *videoCodecctx = NULL;
AVCodecContext *audioCodecctx = NULL;
AVFrame *frame;
AVFrame *frameYUV;
AVPacket avpkt;
AVPacket *pavpkt = &avpkt;

//init
av_register_all();
avformat_network_init();
formatctx = avformat_alloc_context();

//输入文件路径
char *fileName = "Titanic.ts";
if (avformat_open_input(&formatctx,fileName,NULL,NULL)!=0)
{
printf("could not open input stream.\n");
return -1;
}
if (avformat_find_stream_info(formatctx, NULL) < 0)
{
printf("could not find stream information.\n");
return -1;
}

//output file
FILE *outputfile_video = nullptr;
FILE *outputfile_audio = nullptr;
char *outputfilename_video = "output_video.yuv";
char *outputfilename_audio = "output_audio.pcm";
fopen_s(&outputfile_video, outputfilename_video, "wb");
fopen_s(&outputfile_audio, outputfilename_audio, "wb");

//==============video================
//find videoindex
int videoindex = av_find_best_stream(formatctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (videoindex < 0)
{
printf("could not find a video stream.\n");
return -1;
}

//find the video decoder
videoCodecctx = avcodec_alloc_context3(NULL);
if (videoCodecctx == NULL)
{
printf("could not allocate video AVCodecContext.\n");
return -1;
}
avcodec_parameters_to_context(videoCodecctx, formatctx->streams[videoindex]->codecpar);
videoCodec = avcodec_find_decoder(videoCodecctx->codec_id);
if (videoCodec == NULL)
{
printf("vidoe codec not found.\n");
return -1;
}

//open the video decoder
if (avcodec_open2(videoCodecctx, videoCodec, NULL) < 0)
{
printf("could not open video codec.\n");
return -1;
}
//=====================================

//================audio===================
//find audioindex
int audioindex = av_find_best_stream(formatctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if (audioindex < 0)
{
printf("could not find a audio stream.\n");
return -1;
}

//find the audio decoder
audioCodecctx = avcodec_alloc_context3(NULL);
if (audioCodecctx == NULL)
{
printf("could not allocate audio AVCodecContext.\n");
return -1;
}
avcodec_parameters_to_context(audioCodecctx, formatctx->streams[audioindex]->codecpar);
audioCodec = avcodec_find_decoder(audioCodecctx->codec_id);
if (audioCodec == NULL)
{
printf("audio codec not found.\n");
return -1;
}

//open the audio decoder
if (avcodec_open2(audioCodecctx, audioCodec, NULL) < 0)
{
printf("could not open audio codec.\n");
return -1;
}
//========================================

//output information
printf("---------------- File Information --------------\n");
av_dump_format(formatctx, videoindex, fileName, 0);
printf("------------------------------------------------\n");

//pre decode
av_init_packet(&avpkt);
frame = av_frame_alloc();
frameYUV = av_frame_alloc();
int video_dst_bufsize = av_image_alloc((uint8_t**)frameYUV->data, frameYUV->linesize, videoCodecctx->width, videoCodecctx->height, videoCodecctx->pix_fmt, 1);
printf("decode video file %s to %s and %s\n", fileName, outputfilename_video, outputfilename_audio);

//decode
int frame_count = 0;
while (av_read_frame(formatctx,pavpkt)>=0)
{
if (pavpkt->stream_index == videoindex)
{
if (avcodec_send_packet(videoCodecctx, pavpkt) != 0){
printf("input AVPacket to video decoder failed!\n");
return -1;
}
while (0 == avcodec_receive_frame(videoCodecctx, frame)){
av_image_copy((uint8_t **)frameYUV->data,frameYUV->linesize,(const uint8_t **)frame->data,frame->linesize,videoCodecctx->pix_fmt,videoCodecctx->width,videoCodecctx->height);
fwrite(frameYUV->data[0], 1, video_dst_bufsize, outputfile_video);
printf("decoded frame index: %d\n", frame_count);
frame_count++;
}
}
else if (pavpkt->stream_index == audioindex)
{
if (avcodec_send_packet(audioCodecctx, pavpkt) != 0){
printf("input AVPacket to audio decoder failed!\n");
return -1;
}
while (0 == avcodec_receive_frame(audioCodecctx, frame)){
size_t unpadded_linesize = frame->nb_samples*av_get_bytes_per_sample((AVSampleFormat)frame->format);
fwrite(frame->extended_data[0], 1, unpadded_linesize, outputfile_audio);
printf("decoded audio.\n");
}
}
av_packet_unref(pavpkt);
}

fclose(outputfile_video);
fclose(outputfile_audio);
av_frame_free(&frame);
av_frame_free(&frameYUV);
avcodec_close(videoCodecctx);
avcodec_close(audioCodecctx);
avformat_close_input(&formatctx);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ffmpeg