首页 > 编程知识 正文

音频解码,纯音频解码器

时间:2023-05-04 00:49:17 阅读:115481 作者:1655

1. ffmpeg视频解码1

2. ffmpeg视频解码2

3. ffmpeg音频解码1

4. ffmpeg音频解码2

5. ffmpeg音视频解码

6. ffmpeg视频编码1

7. ffmpeg视频编码1 (精简版) )。

8. ffmpeg视频编码2 (基于2(libswscale转换视频)。

9 .使用9. ffmpeg过滤器libavfilter

10. ffmpeg视频编码3 (基于3(libavfilter转换视频) )。

如上所述,已经介绍了单个音频和视频解码,本文结合前面的内容,关于包括音频视频在内的MP4

解码文件,提取其中的音频和视频,并将其保存到不同的文件中。

流程图

源代码# pragma once # define _ stdc _ constant _ macros # define _ CRT _ secure _ no _ warnings extern ' c ' { # includeros 输出视频文件# define output _ video _ file _ name ' LH _ online.YY line efineoutput _ audio _ file _ name ' LH _ online . ret=av codec _ send _ packet (dec _ CTX,pkt ); if(ret0) av_log(null,AV_LOG_ERROR,' errorsendingapacketfordecoding. n ' ); 退出(1; }while(ret=0) ret=avcodec_receive_frame ) dec_CTX,frame ); if(ret==averror(eagain )|| ret==AVERROR_EOF ) return; ELSEif(ret0) av _ log null,AV_LOG_ERROR,' errorreceiveaframefordecoding. n ' ); 退出(1; //此时,1帧的数据已经保存在frame中。 if(type==avmedia_type_video )//要打印的视频帧的帧数printf (视频帧编号3360 % d. n )、//1帧的视频frite(frame-data[0],1,y_size,ofile ); //YF write (帧数据[1],1,y_size/4,ofile ); //uf write (帧数据[2],1,y_size/4,ofile ); //v } else if (type==av media _ type _ audio ) printf (audio frame _ number 3360 % dn )、dec_CTX-frame_ //if(data_size0) av_log ) null,AV_LOG_ERROR,' Failed to calculate data size.n ' ); 退出(1; //遍历采样点for (I=0; i frame-nb_samples; 遍历I ()//通道for (ch=0; ch dec_ctx-channels; ch ) (fwrite )帧数据[ ch ] data_size * I,1,data _ size,ofile ); } } } staticintget _ format _ from _ sample _ fmt (const char * * fmt,enum AVSampleFormat sample_fmt ) {int i; 结构sample _ fmt _ entry { enumavsampleformatsample _ fmt; 常数char * fmt _ be,* fmt_le; } sample _ fmt _ entries [ ]={ av _ sample _ fmt _ U8,' u8 ',{ AV_SAMPLE_FMT_S16,' s16be '

6le" },{ AV_SAMPLE_FMT_S32, "s32be", "s32le" },{ AV_SAMPLE_FMT_FLT, "f32be", "f32le" },{ AV_SAMPLE_FMT_DBL, "f64be", "f64le" },};*fmt = NULL;for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) {struct sample_fmt_entry* entry = &sample_fmt_entries[i];if (sample_fmt == entry->sample_fmt) {*fmt = AV_NE(entry->fmt_be, entry->fmt_le);return 0;}}fprintf(stderr,"sample format %s is not supported as output formatn",av_get_sample_fmt_name(sample_fmt));return -1;}int main(int argc, char* argv[]){AVFormatContext* fmt_ctx = NULL;AVCodecContext* i_dex_ctx = NULL, * a_dex_ctx = NULL;AVFrame* frame;AVPacket* pkt;int ret, i;int i_stream_index = -1, a_stream_index = -1;FILE* i_ofile, * a_ofile;//打开输入文件,并为fmt_ctx分配空间if (avformat_open_input(&fmt_ctx, INPUT_FILE_NAME, NULL, NULL)) {av_log(NULL, AV_LOG_ERROR, "Codec not open source file.n");exit(1);}//获取流信息if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {av_log(NULL, AV_LOG_ERROR, "Could not find stream information.n");exit(1);}for (i = 0; i < fmt_ctx->nb_streams; i++) {AVStream* in_stream = fmt_ctx->streams[i];AVCodecParameters* in_codecpar = in_stream->codecpar;if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {continue;}//获取解码器AVCodec* codec = avcodec_find_decoder(in_codecpar->codec_id);if (!codec) {av_log(NULL, AV_LOG_ERROR, "Codec not found.n");exit(1);}//分配解析器上下文AVCodecContext* c = avcodec_alloc_context3(codec);if (!c) {av_log(NULL, AV_LOG_ERROR, "Could not allocate video codec context.n");exit(1);}//把输入流的编解码参数复制到我们的解码器上if (avcodec_parameters_to_context(c, in_codecpar) < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to copy %s codec parameters to decoder contextn");exit(1);}//打开解码器if (avcodec_open2(c, codec, NULL) < 0) {av_log(NULL, AV_LOG_ERROR, "Could not open codec.n");exit(1);}//初始化外部变量if (in_codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {a_dex_ctx = c;a_stream_index = i;}else if (in_codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {i_dex_ctx = c;i_stream_index = i;}}//如果音视频有一个没有,直接退出程序if (i_stream_index == -1 || a_stream_index == -1) {av_log(NULL, AV_LOG_ERROR, "video or audio stram index is not find .n");exit(1);}//分配AVPacketpkt = av_packet_alloc();if (!pkt) {exit(1);}//分配AVFrameframe = av_frame_alloc();if (!frame) {exit(1);}//打开输出文件//视频i_ofile = fopen(OUTPUT_VIDEO_FILE_NAME, "wb+");if (!i_ofile) {av_log(NULL, AV_LOG_ERROR, "Could not open s.n", OUTPUT_VIDEO_FILE_NAME);exit(1);}//音频a_ofile = fopen(OUTPUT_AUDIO_FILE_NAME, "wb+");if (!a_ofile) {av_log(NULL, AV_LOG_ERROR, "Could not open s.n", OUTPUT_AUDIO_FILE_NAME);exit(1);}//从文件读取帧while (av_read_frame(fmt_ctx, pkt) >= 0) {//只处理视频流if (pkt->stream_index == i_stream_index) {decode(i_dex_ctx, frame, pkt, i_ofile, AVMEDIA_TYPE_VIDEO);}else if (pkt->stream_index == a_stream_index) {decode(a_dex_ctx, frame, pkt, a_ofile, AVMEDIA_TYPE_AUDIO);}av_packet_unref(pkt);}//flush 解码器decode(i_dex_ctx, frame, NULL, i_ofile, AVMEDIA_TYPE_VIDEO);decode(a_dex_ctx, frame, NULL, a_ofile, AVMEDIA_TYPE_AUDIO);printf("Demuxing succeeded.n");if (i_stream_index != -1) {enum AVPixelFormat pix_fmt = i_dex_ctx->pix_fmt;printf("Play the output video file with the command:n""ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %sn",av_get_pix_fmt_name(pix_fmt), i_dex_ctx->width, i_dex_ctx->height,OUTPUT_VIDEO_FILE_NAME);}if (a_stream_index != -1) {enum AVSampleFormat sfmt = a_dex_ctx->sample_fmt;int n_channels = a_dex_ctx->channels;const char* fmt;//如果为planar,转换为packed格式if (av_sample_fmt_is_planar(sfmt)) {const char* packed = av_get_sample_fmt_name(sfmt);sfmt = av_get_packed_sample_fmt(sfmt);n_channels = 1;}if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0) {exit(1);}printf("Play the output audio file with the command:n""ffplay -f %s -ac %d -ar %d %sn",fmt, n_channels, a_dex_ctx->sample_rate,OUTPUT_AUDIO_FILE_NAME);}//资源释放fclose(i_ofile);fclose(a_ofile);avcodec_free_context(&i_dex_ctx);avcodec_free_context(&a_dex_ctx);av_frame_free(&frame);av_packet_free(&pkt);return 0;}

运行该程序,可见下面如下面的打印信息:

其中音频共1308帧,视频510帧,其中视频是yuv420p的格式,宽高为512*288。音频为一个有1个声道,采样率为44100HZ,采样格式为fltp的文件。

看一下解码出来的文件:

可见生成了两个文件,一个pcm文件(lh_online.pcm),一个yuv文件(lh_online.yuv)。

下面使用ffplay播放两个文件:
首先播放视频:

ffplay -f f32le -ac 1 -ar 44100 lh_online.pcm


此时你应该可以看见与MP4一样的视频,可见,视频文件是正常的,证明视频解码成功了。

然后播放音频:

ffplay -f f32le -ac 1 -ar 44100 lh_online.pcm


此时你应该能听到和MP4文件一致的声音,可见,音频解码成功。

到此,解码部分的内容就已经说完了。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。