FFmpeg音视频编解码实践总结
PS:由于目前开发RTSP服务器传输模块时用到了h264文件,所以攻了一段时间去实现h264的视频编解码,借用FFmpeg SDK实现了任意文件格式之间的转换,并实现了流媒体实时播放,目前音视频同步需要稍加完善,视频编码代码已成功移植到Visual Stdio平台,如有需要的留下邮箱
以下文档来自FFmpeg工程组(http://www.ffmpeg.com.cn/index.php开发事例)
实现转码一个普通视频文件为视频mpeg4,音频mp3的功能的程序
本程序源引自FFmpeg工程组,实现转码一个普通视频文件为视频mpeg4,音频mp3的功能
#include <avcodec.h>
#include <avformat.h>
#include <stdio.h>
#include <avutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main(int argc,char **argv)
{
const char *input_file_name="/root/movies/ddh1.mpg";
av_register_all();//注册库中所有可用的文件格式和编码器
AVFormatContext *ic;
//输入文件处理部分
ic=av_alloc_format_context();
if(av_open_input_file(&ic,input_file_name,NULL,0,NULL)!=0)
{
printf("can't open the file %s\n",input_file_name);
exit(1);
}//打开输入文件
if(av_find_stream_info(ic)<0)
{
printf("can't find suitable codec parameters\n");
exit(1);
}//取出流信息
dump_format(ic,0,input_file_name,0);//列出输入文件的相关流信息
int i;
int videoindex=-1;int audioindex=-1;
for(i=0;i<ic->nb_streams;i++)
{
if(ic->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
{
videoindex=i;
//printf("video\n");
}
else if(ic->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
{
//printf("audio\n");
audioindex=i;
}
}
if(videoindex==-1)
{
printf("can't find video stream\n");
exit(1);
}//没有找到视频流
AVCodecContext *vCodecCtx;
vCodecCtx=ic->streams[videoindex]->codec;//取得视频流编码上下文指针
AVCodec *vCodec;
vCodec=avcodec_find_decoder(vCodecCtx->codec_id);
if(vCodec==NULL)
{
printf("can't find suitable video decoder\n");
exit(1);
}//找到合适的视频解码器
if(avcodec_open(vCodecCtx,vCodec)<0)
{
printf("can't open the video decoder\n");
exit(1);
}//打开该视频解码器
if(audioindex==-1)
{
printf("can't find audio stream\n");
exit(1);
}//没有找到音频流
AVCodecContext *aCodecCtx;
aCodecCtx=ic->streams[audioindex]->codec;
AVCodec *aCodec;
aCodec=avcodec_find_decoder(aCodecCtx->codec_id);
if(aCodec==NULL)
{
printf("can't find suitable audio decoder\n");
exit(1);
}//找到合适的音频解码器
if(avcodec_open(aCodecCtx,aCodec)<0)
{
printf("can't open the audio decoder\n");
exit(1);
}//打开该音频解码器
//下面为输出文件处理部分
const char *output_file_name="/root/123.avi";
AVOutputFormat *fmt;
AVFormatContext *oc;
AVCodecContext *oVcc,*oAcc;
AVCodec *oVc,*oAc;
AVStream *video_st,*audio_st;
AVFrame *oVFrame,*oAFrame;
double video_pts;
oVFrame=avcodec_alloc_frame();
fmt=guess_format(NULL,output_file_name,NULL);
if(!fmt)
{
printf("could not deduce output format from outfile extension\n");
exit(0);
}//判断是否可以判断输出文件的编码格式
oc=av_alloc_format_context();
if(!oc)
{
printf("Memory error\n");
exit(0);
}
oc->oformat=fmt;
pstrcpy(oc->filename,sizeof(oc->filename),output_file_name);
video_st=av_new_stream(oc,0);
if(!video_st)
{
printf("could not alloc video stream\n");
exit(0);
}
oVcc=avcodec_alloc_context();
oVcc=video_st->codec;
oVcc->codec_id=CODEC_ID_MPEG4;
oVcc->codec_type=CODEC_TYPE_VIDEO;
oVcc->bit_rate=2500000;
oVcc->width=704;
oVcc->height=480;
oVcc->time_base=vCodecCtx->time_base;
oVcc->gop_size=vCodecCtx->gop_size;
//oVcc->pix_fmt=vCodecCtx->pix_fmt;
oVcc->pix_fmt=vCodecCtx->pix_fmt;
oVcc->max_b_frames=vCodecCtx->max_b_frames;
video_st->r_frame_rate=ic->streams[videoindex]->r_frame_rate;
audio_st=av_new_stream(oc,oc->nb_streams);
if(!audio_st)
{
printf("could not alloc audio stream\n");
exit(0);
}
avcodec_get_context_defaults2(audio_st->codec,CODEC_TYPE_AUDIO);
oAcc=avcodec_alloc_context();
oAcc=audio_st->codec;
oAcc->codec_id=CODEC_ID_MP3;
oAcc->codec_type=CODEC_TYPE_AUDIO;
oAcc->bit_rate=aCodecCtx->bit_rate;
oAcc->sample_rate=aCodecCtx->sample_rate;
oAcc->channels=2;
if (av_set_parameters(oc, NULL) < 0)
{
printf( "Invalid output format parameters\n");
exit(0);
}//设置必要的输出参数
strcpy(oc->title,ic->title);
strcpy(oc->author,ic->author);
strcpy(oc->copyright,ic->copyright);
strcpy(oc->comment,ic->comment);
strcpy(oc->album,ic->album);
oc->year=ic->year;
oc->track=ic->track;
strcpy(oc->genre,ic->genre);
dump_format(oc,0,output_file_name,1);//列出输出文件的相关流信息
oVc=avcodec_find_encoder(CODEC_ID_MPEG4);
if(!oVc)
{
printf("can't find suitable video encoder\n");
exit(0);
}//找到合适的视频编码器
if(avcodec_open(oVcc,oVc)<0)
{
printf("can't open the output video codec\n");
exit(0);
}//打开视频编码器
oAc=avcodec_find_encoder(CODEC_ID_MP3);
if(!oAc)
{
printf("can't find suitable audio encoder\n");
exit(0);
}//找到合适的音频编码器
if(avcodec_open(oAcc,oAc)<0)
{
printf("can't open the output audio codec");
exit(0);
}//打开音频编码器
/*if(url_exist(output_file_name))
{
printf("the output file name %s has exist,please select other\n",output_file_name);
exit(0);
}//判断该输出文件是否已经存在*/
if (!(oc->flags & AVFMT_NOFILE))
{
if(url_fopen(&oc->pb,output_file_name,URL_WRONLY)<0)
{
printf("can't open the output file %s\n",output_file_name);
exit(0);
}//打开输出文件
}
if(!oc->nb_streams)
{
fprintf(stderr,"output file dose not contain any stream\n");
exit(0);
}//查看输出文件是否含有流信息
if(av_write_header(oc)<0)
{
fprintf(stderr, "Could not write header for output file\n");
exit(1);
}[/i][/i]
AVPacket packet;
uint8_t *ptr,*out_buf;
int out_size;
static short *samples=NULL;
static unsigned int samples_size=0;
uint8_t *video_outbuf,*audio_outbuf;int video_outbuf_size,audio_outbuf_size;
video_outbuf_size=400000;
video_outbuf= (unsigned char *) malloc(video_outbuf_size);
audio_outbuf_size = 10000;
audio_outbuf = av_malloc(audio_outbuf_size);
int flag;int frameFinished;int len;int frame_index=0,ret;
while(av_read_frame(ic,&packet)>=0)//从输入文件中读取一个包
{
if(packet.stream_index==videoindex)//判断是否为当前视频流中的包
{
len=avcodec_decode_video(vCodecCtx,oVFrame,&frameFinished,packet.data,packet.size);//若为视频包,解码该视频包
if(len<0)
{
printf("Error while decoding\n");
exit(0);
}
if(frameFinished)//判断视频祯是否读完
{
fflush(stdout);
oVFrame->pts=av_rescale(frame_index,AV_TIME_BASE*(int64_t)oVcc->time_base.num,oVcc->time_base.den);
oVFrame->pict_type=0;
out_size = avcodec_encode_video(oVcc, video_outbuf, video_outbuf_size, oVFrame);
if (out_size > 0)
{
AVPacket pkt;
av_init_packet(&pkt);
if(oVcc->coded_frame && oVcc->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
pkt.flags = packet.flags;
pkt.stream_index= video_st->index;
pkt.data= video_outbuf;
pkt.size= out_size;
ret=av_write_frame(oc, &pkt);
}
frame_index++;
}
else
ret=av_write_frame(oc, &packet);
//img_convert((AVPicture *)vFrame, PIX_FMT_RGB24, (AVPicture*)oVFrame, oVcc->pix_fmt,oVcc->width,oVcc-
>height);
//SaveFrame(vFrame,oVcc->width,oVcc->height,frame_index);
if(ret!=0)
{
printf("while write video frame error\n");
exit(0);
}
}
else if(packet.stream_index==audioindex)
{
len=packet.size;
ptr=packet.data;
int ret=0;
while(len>0)
{
out_buf=NULL;
out_size=0;
if(&packet)
samples=av_fast_realloc(samples,&samples_size,FFMAX(packet.size*sizeof
(*samples),AVCODEC_MAX_AUDIO_FRAME_SIZE));
out_size=samples_size;
ret=avcodec_decode_audio(aCodecCtx,samples,&out_size,ptr,len);//若为音频包,解码该音频包
if(ret<0)
{
printf("while decode audio failure\n");
exit(0);
}
fflush(stdout);
ptr+=ret;
len-=ret;
if(out_size<=0)
continue;
out_buf=(uint8_t *)samples;
AVPacket pkt;
av_init_packet(&pkt);
pkt.size= avcodec_encode_audio(oAcc, audio_outbuf, audio_outbuf_size, out_buf);
pkt.pts= av_rescale_q(oAcc->coded_frame->pts, oAcc->time_base, audio_st->time_base);
pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index= audioindex;
pkt.data= audio_outbuf;
if (av_write_frame(oc, &pkt) != 0)
{
fprintf(stderr, "Error while writing audio frame\n");
exit(1);
}
}
}
av_free_packet(&packet);
}
av_write_trailer(oc);
for(i = 0; i < oc->nb_streams; i++)
{
av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]);
}
url_fclose(oc);
av_free(oc);
av_free(oVFrame);
av_free(out_buf);
avcodec_close(vCodecCtx);
avcodec_close(aCodecCtx);
av_close_input_file(ic);
}
最近一直很忙 花时间整理了一份 希望大家多多交流ffmpeg视频编解码方面的知识 接下来会抽时间总结一篇RTP传输协议的文章 好了 废话不说 附上链接自己下载
source download: http://files.cnblogs.com/msopengl/ffmpegh264codec.rar
FFmpeg音视频编解码实践总结的更多相关文章
- [转帖]AVS音视频编解码技术了解
AVS高清立体视频编码器 电视技术在经历了从黑白到彩色.从模拟到数字的技术变革之后正在酝酿另一场技术革命,从单纯观看二维场景的平面电视跨越到展现三维场景的立体电视3DTV.3DTV系统的核心问题之一是 ...
- 音视频编解码技术(一):MPEG-4/H.264 AVC 编解码标准
一.H264 概述 H.264,通常也被称之为H.264/AVC(或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC) 1. H.264视频编解码的意义 H.264的出现就是为了创 ...
- 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...
- 集显也能硬件编码:Intel SDK && 各种音视频编解码学习详解
http://blog.sina.com.cn/s/blog_4155bb1d0100soq9.html INTEL MEDIA SDK是INTEL推出的基于其内建显示核心的编解码技术,我们在播放高清 ...
- 【miscellaneous】各种音视频编解码学习详解
编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...
- 基于ffmpeg的简单音视频编解码的例子
近日需要做一个视频转码服务器,对我这样一个在该领域的新手来说却是够我折腾一番,在别人的建议下开始研究开源ffmpeg项目,下面是在代码中看到的一 段例子代码,对我的学习非常有帮助.该例子代码包含音频的 ...
- 各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式
编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放 license收费等 ...
- 音视频编解码问题:javaCV如何快速进行音频预处理和解复用编解码(基于javaCV-FFMPEG)
前言: 前面我用了很多章实现了javaCV的基本操作,包括:音视频捕捉(摄像头视频捕捉和话筒音频捕捉),推流(本地音视频或者摄像头话筒混合推流到服务器),转流(rtsp->rtmp),收流(录制 ...
- 音视频编解码——LAME
一.LAME简介 LAME是目前非常优秀的一种MP3编码引擎,在业界,转码成Mp3格式的音频文件时,最常用的就是LAME库.当达到320Kbit/s时,LAME编码出来的音频质量几乎可以和CD的音质相 ...
随机推荐
- 记一次CDH修改IP
因机房服务器搬迁,需要修改CDH ip ,集群中有6台服务器. 其中配置了ldap,其中卡在了ldap中的坑太深,所以记录一下. 一.服务器IP等地址修改 1.首先在安装cloudera-manage ...
- 怎样使用Entityframework.Extended
这个插件真的非常有用,我们能够使用下面语法来简化我们的工作,下面不过演示样例: Deleting <strong>//delete all users where FirstName ma ...
- sql的一些知识_where
简单相同查询,查询age=22的三列信息,并按照降序排列 ORDER BY weight DESC 此外,where还支持一下判断操作符 值得注意的是,如果比较的值为数值,则不需要加引号,如果是字符, ...
- js 字符串常用方法
数组方面 1.push:向数组尾部增加内容,返回的是新数组的长度. var arr = [1,2,3]; console.log(arr); var b = arr.push(4); console. ...
- python(35)- 异常处理
一 错误和异常 part1:程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 ...
- mysql truncate table命令使用总结
truncate使用注意 由于上过truncate table a_table命令一次当,将教训记录下来,以示警戒! mysql truncate table a_table命令受影响结果说明 ...
- Android SQLite性能分析
作为Android预置的数据库模块,对SQLite的深入理解是很有必要的,能够从中找到一些优化的方向. 这里对SQLite的性能和内存进行了一些測试分析.对照了不同操作的运行性能和内存占用的情况,粗略 ...
- mysql 找出外键等约束
找出employee表的所有外键约束 select TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_C ...
- JS实现搜索模糊匹配
Js代码 <script type="text/javascript"> var websites = [["1231","账上1&q ...
- 【上】安全HTTPS-全面具体解释对称加密,非对称加密,数字签名,数字证书和HTTPS
一,对称加密 所谓对称加密.就是它们在编码时使用的密钥e和解码时一样d(e=d),我们就将其统称为密钥k. 对称加解密的步骤例如以下: 发送端和接收端首先要共享同样的密钥k(即通信前两方都须要知道相应 ...