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的音质相 ...
随机推荐
- luogu P1879 [USACO06NOV]玉米田Corn Fields
题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ...
- Java1.8新特性——接口改动和Lambda表达式
Java1.8新特性——接口改动和Lambda表达式 摘要:本文主要学习了Java1.8的新特性中有关接口和Lambda表达式的部分. 部分内容来自以下博客: https://www.cnblogs. ...
- arcgis andriod开发程序实例,有图有真相
本程序使用Google公司最新开发工具andriod studio开发,实现了地图的加载,放大,缩小,GPS定位,画点.线,面工具,本程序有偿提供源代码 主界面,加载tpk切片 放大: 加载geoda ...
- Caused by: java.io.FileNotFoundException: rmi_keystore.jks (没有那个文件或目录)
解决方法:修改jmeter.properites: server.rmi.ssl.disable=true,关闭ssl功能 参考: https://blog.csdn.net/nielinqi520/ ...
- 【Todo】各种语言里面的for循环 & loop
会的语言多了,不同语言的语法就会混淆.整理了一下. Java里面: 普通的for循环之外: 有以下格式: for (int x : intarr) { } JS里面: }; for (x in per ...
- python入门之搭建环境
进入以下网站:python.org 选择你喜欢(需要)的版本下载 点击下载即可,本次提供下载:python3.6.3 (国外架设,非常慢) ,用百度的平台吧:python3.6.1,多谢百度. 开始安 ...
- ubuntu boot空间不足
在安装 Ubuntu的时候 , 给/boot文件目录分配空间的时候,是100M,/boot可以单独分成一个区,也可以不单独分,在/(根目录)下也会自动为其创建一个boot目录.顺便提一下,Linux分 ...
- python(39)- 网络编程socket练习
基于tcp的套接字实现远程执行命令的操作 #服务端 import socket import subprocess phone=socket.socket(socket.AF_INET,socket. ...
- 在Linux中将php-fpm配置成服务的方法
1.配置php-fpm.conf vi /usr/local/php/etc/php-fpm.conf php-fpm.pid 目录必须指向:/usr/local/php/var/run/php-fp ...
- 为基于 x86 的 Android* 游戏选择合适的引擎
摘要 游戏开发者知道 Android 中蕴藏着巨大的机遇. 在 Google Play 商店的前 100 款应用中,约一半是游戏应用(在利润最高的前 100 款应用中.它们所占的比例超过 90%). ...