配置ffmpeg,只留下某些音频的配置:

./configure --enable-shared --disable-yasm --enable-memalign-hack --enable-gpl --enable-cross-compile --prefix=/home/liqinghan/workspace/ffmpeg-3.2./_install --arch=arm --target-os=linux --cross-prefix=arm-hisiv400-linux- --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-avdevice --disable-network --disable-dct --disable-dwt --disable-error-resilience --disable-lsp --disable-lzo --disable-faan --disable-pixelutils --disable-everything --disable-amd3dnow --disable-amd3dnowext --disable-power8 --disable-mmx --disable-mmxext --disable-debug --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm --enable-decoder=alac --enable-decoder=ac3 --enable-decoder=adpcm_ima_wav --enable-decoder=adpcm_4xm --enable-decoder=adpcm_g722 --enable-decoder=adpcm_g726 --enable-decoder=adpcm_yamaha --enable-decoder=flac --enable-decoder=g729 --enable-decoder=iac --enable-decoder=mp3 --enable-decoder=mp3adu --enable-decoder=mp3adufloat --enable-decoder=mp3float --enable-decoder=mp3on4 --enable-decoder=mp3on4float --enable-decoder=pcm_alaw --enable-decoder=pcm_mulaw --enable-decoder=ape

编写音频解码接口:

ifndef _AV_AUDIO_DECODER_H_
#define _AV_AUDIO_DECODER_H_ #pragma pack(push)
#pragma pack(1) typedef struct { int channel; //通道号
int sample_Rate; //采样率
int band_Width; //位宽
int frmsize; //一个帧的长度
int bits_per_coded_sample; //一个byte编码后占bit位
int num_point_per_pack; //包的点数
}AVaudioDeocerAttr;
#pragma pack(pop)
/*
Id:ffmepg对应编解码的id!!
*/
int audio_decoder_create(int id,AVaudioDeocerAttr decoderAttr);
int audio_decoder_destroy(void);
void audio_decode_start(void);
void audio_decode_stop(void);
/*
*collision: < 0 阻塞写入, 0: 非阻塞, >0:超时(us)
*/
int aduio_send_packet(char* packet,int size,int64_t pts,int collision);
int audio_send_packet_stop(void);
int audio_decode_getframe(char* buf,int *size,int64_t *pts);

内部实现

#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <sys/time.h> #include "libavutil/internal.h"
#include "libavcodec/avcodec.h"
#include "avaudiodecoder.h" #if HAVE_SYS_RESOURCE_H
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
#elif HAVE_GETPROCESSTIMES
#include <windows.h>
#endif
#if HAVE_GETPROCESSMEMORYINFO
#include <windows.h>
#include <psapi.h>
#endif
#if HAVE_SETCONSOLECTRLHANDLER
#include <windows.h>
#endif #if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif #if HAVE_TERMIOS_H
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
#elif HAVE_KBHIT
#include <conio.h>
#endif #if HAVE_PTHREADS
#include <pthread.h>
#endif #include <time.h> #define _AV_AUDIO_DECODER_DEBUG_(fmt,args...) \
do{ \
printf("[av_audio_decoder_debug]");\
printf(fmt,##args); \
}while() static AVCodec *codec = NULL;
static AVCodecContext *codecContext= NULL;
static AVPacket avPkt;
static AVFrame *decodedFrame = NULL;
static int shmid;
static pthread_mutex_t mutex; static int vb_initialized = ; #pragma pack(push)
#pragma pack(1)
//共享内存区!
typedef struct{
int writeable;
int memsize;
int bufsize;
int64_t pts;
char buf[]; //定义一个不占为位置的符号,数据的起始地址
}AVshareMemBuf; #pragma pack(pop) static AVshareMemBuf* outMemBuf;
static AVshareMemBuf* userBuf; static void* shmembuf; static pthread_t pid; static int getframectrl = ; static void* audio_decode_start_thread(void* param);
static void audio_get_frame_defaults(AVFrame *frame);
static void audio_decoder_vb_destroy(void);
static void audio_decoder_vb_create(int frmSize); static int64_t get_cur_time(void); static int64_t get_cur_time(void){
int64_t time;
struct timeval tv;
gettimeofday(&tv,NULL);
time = tv.tv_sec**;
time = time + tv.tv_usec;
return time;
} static void audio_get_frame_defaults(AVFrame *frame)
{
if (frame->extended_data != frame->data)
av_freep(&frame->extended_data); memset(frame, , sizeof(*frame)); frame->pts =
frame->pkt_dts = AV_NOPTS_VALUE;
#if FF_API_PKT_PTS
FF_DISABLE_DEPRECATION_WARNINGS
frame->pkt_pts = AV_NOPTS_VALUE;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
frame->best_effort_timestamp = AV_NOPTS_VALUE;
frame->pkt_duration = ;
frame->pkt_pos = -;
frame->pkt_size = -;
frame->key_frame = ;
frame->sample_aspect_ratio = (AVRational){ , };
frame->format = -; /* unknown */
frame->extended_data = frame->data;
frame->color_primaries = AVCOL_PRI_UNSPECIFIED;
frame->color_trc = AVCOL_TRC_UNSPECIFIED;
frame->colorspace = AVCOL_SPC_UNSPECIFIED;
frame->color_range = AVCOL_RANGE_UNSPECIFIED;
frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
frame->flags = ;
} static void audio_decoder_vb_destroy(void){ shmdt(shmembuf);
vb_initialized = ;
shmembuf =NULL;
} static void audio_decoder_vb_create(int frmSize){ //
//we must create vb buffer for videoserver put!!!
// if(vb_initialized) return; shmid = shmget(0x7090, sizeof(AVshareMemBuf) + frmSize, IPC_CREAT | ); //第二个参数shmaddr为NULL,内核会自动选择地址映射
shmembuf = shmat(shmid, NULL, ); userBuf = (AVshareMemBuf*)shmembuf;
userBuf->writeable = ;
userBuf ->size = frmSize;
av_init_packet(&avPkt);
vb_initialized = ;
} int audio_decoder_create(int id,AVaudioDeocerAttr decoderAttr){ int audioSize;
//注册解码器,看源码可以知道就是定义每个解码器,参数和回调函数。 regster_all_audio_decoder();
codec = avcodec_find_decoder(id); if(codec == NULL){ _AV_AUDIO_DECODER_DEBUG_("cannot find deocder \n");
return -;
}
//给解码器申请上下文,就是处理空间
codecContext = avcodec_alloc_context3(codec); codecContext->sample_rate = decoderAttr.sample_Rate;
codecContext->channels = decoderAttr.channel;
codecContext->bits_per_coded_sample = decoderAttr.bits_per_coded_sample; //打开解码器
/* open it */
int s32Ret = avcodec_open2(codecContext, codec, NULL);
if ( s32Ret < )
{
avcodec_free_context(&codecContext); _AV_AUDIO_DECODER_DEBUG_("can not open codec\n"); return -;
}
audioSize = decoderAttr.num_point_per_pack; outMemBuf =(AVshareMemBuf*)malloc(sizeof(AVshareMemBuf) + audioSize);
outMemBuf->size = audioSize;
outMemBuf->writeable =; pthread_mutex_init (&mutex,NULL);
//创建VB
audio_decoder_vb_create(decoderAttr.frmsize); return ; } int audio_decoder_destroy(void){ avcodec_close(codecContext); av_free(codecContext); av_frame_free(&decodedFrame); free(outMemBuf); pthread_mutex_destroy(&mutex); if(shmctl(shmid, IPC_RMID, ) == -)
{
_AV_AUDIO_DECODER_DEBUG_("shmctl(IPC_RMID) failed\n");
//exit(EXIT_FAILURE);
} return ;
} int aduio_send_packet(char* packet,int size,int64_t pts,int collision){ audio_decoder_vb_create(size); if(packet == NULL) {_AV_AUDIO_DECODER_DEBUG_("audio packet is null\n"); return -;} if(collision < ){ while(userBuf->writeable == ){ } }
else if(collision ==){ if(userBuf->writeable == ) { _AV_AUDIO_DECODER_DEBUG_("decoder buffer is full\n");
return -;
}
}
else{ uint64_t time = get_cur_time(); while(userBuf->writeable == ){ if((get_cur_time() - time) > collision) { _AV_AUDIO_DECODER_DEBUG_("decoder buffer is full\n"); return -;
}
} } if(userBuf->size < size){ _AV_AUDIO_DECODER_DEBUG_("userBuf->size:%d,size:%d,frame size is too larger\n",userBuf->size,size); return -;
} memcpy(userBuf->buf,packet,size); userBuf->writeable = ;
userBuf->pts = pts;
userBuf->size = size; return ; } int audio_send_packet_stop(void){ audio_decoder_vb_destroy(); } void audio_decode_start(void){ if(getframectrl) return; getframectrl =; pthread_create(&pid,NULL,audio_decode_start_thread,NULL); } void audio_decode_stop(void){ if(getframectrl ==) return; getframectrl =; pthread_join(pid,NULL); } void* audio_decode_start_thread(void* param){ int got_frame = ; AVshareMemBuf* membuf = NULL; membuf = (AVshareMemBuf*)malloc(sizeof(AVshareMemBuf) + userBuf->size); while(getframectrl){ if(userBuf->writeable == ){ membuf->pts = userBuf->pts;
membuf->size = userBuf->size;
memcpy(membuf->buf,userBuf->buf,membuf->size);
userBuf->writeable = ; avPkt.data = membuf->buf;
avPkt.size = membuf->size;
avPkt.pts = membuf->pts; if (decodedFrame == NULL)
{
decodedFrame = av_frame_alloc(); if (decodedFrame == NULL)
{
_AV_AUDIO_DECODER_DEBUG_("malloc frame vb error!!!\n");
return ;
}
} else{
audio_get_frame_defaults(decodedFrame);
} got_frame = ; int len = avcodec_decode_audio4(codecContext, decodedFrame, &got_frame, &avPkt); if (len < )
{
// return 0;
_AV_AUDIO_DECODER_DEBUG_("decoder error!,you input frame is error!! \n");
} if (got_frame)
{
/* if a frame has been decoded, output it */
int data_size = av_samples_get_buffer_size(NULL, codecContext->channels,
decodedFrame->nb_samples,
codecContext->sample_fmt, ); if(outMemBuf->size >= data_size){
//lock!!
if(outMemBuf->writeable){ pthread_mutex_lock(&mutex); _AV_AUDIO_DECODER_DEBUG_("data_size:%d,outMemBuf->size:%d,codecContext->bits_per_raw_sample:%d\n",data_size,outMemBuf->size,codecContext->bits_per_raw_sample); memcpy(outMemBuf->buf,decodedFrame->data[],data_size); outMemBuf->writeable = ;
outMemBuf->pts = decodedFrame->pts; pthread_mutex_unlock(&mutex); }
else {
_AV_AUDIO_DECODER_DEBUG_("decoder buff is full \n");
} }
else{
_AV_AUDIO_DECODER_DEBUG_("outMemBuf->size:%d,data_size:%d;after decoder packet size is error \n",outMemBuf->size,data_size);
}
} } } free(membuf);
return NULL;
} /*
*获取解码后数据,音频原始数据,(PCM码)
*/
int audio_decode_getframe(char* buf,int *size,int64_t *pts){
int ret =-;
pthread_mutex_lock(&mutex);
if(outMemBuf->writeable == ){ memcpy(buf,outMemBuf->buf,outMemBuf->size);
*pts = outMemBuf->pts;
*size = outMemBuf->size;
outMemBuf->writeable = ;
ret = ;
}
pthread_mutex_unlock(&mutex);
return ret; }
Makefile:
CROSS_COMPILE=
SRC_DIR = ./
SRC := $(wildcard $(SRC_DIR)/*.c)
OBJS := $(SRC:%.c=%.o)
OBJ := .o
A := a
C := c
CC := $(CROSS_COMPILE)gcc
#定义自己库名,生成两个,库动态和静态
SOLIB := libavaudiodecoder.so
ALIB := libavaudiodecoder.a
#添加ffmpeg依赖库
ffmpeg_obj += $(wildcard ../libavcodec/*.o)
ffmpeg_obj += $(wildcard ../libavcodec/arm/*.o)
ffmpeg_obj += $(wildcard ../libavutil/*.o)
ffmpeg_obj += $(wildcard ../libavutil/arm/*.o) #####################################
LIBRARY_LINK = $(CROSS_COMPILE)ar -scr
INC_FLAGS += -I..
#-g加上调试增加数据量,应该去掉
CFLAGS := -Wall -g -shared -fPIC
LD_FLAGS = -lpthread -lm -ldl
MYLIB = $(SOLIB) $(ALIB)
all: $(MYLIB)
%.o:%.c
$(CC) -c $(INC_FLAGS) $(CFLAGS) $<
$(SOLIB):$(OBJS)
$(CC) $(INC_FLAGS) $(CFLAGS) -o $@ $^ $(LD_FLAGS) $(ALIB):$(OBJS) $(ffmpeg_obj)
$(LIBRARY_LINK) $@ $^ $(OBJS)
.PHONY : clean all
clean:
@rm -f *.so
@rm -f *.o
@rm -f *.a

FFmpeg 裁剪——音频解码的更多相关文章

  1. FFMPEG视音频解码【一】

    多媒体的时代,得多了解点编解码的技术才行,而ffmpeg为我们提供了一系列多媒体编解码的接口,如何用好这些接口达到自己所需要的目的,这也是一门重要的学问. 要是了解得不够,总是会遇到一堆又一堆问题:网 ...

  2. [总结]FFMPEG视音频编解码零基础学习方法--转

    ffmpeg编解码学习   目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ...

  3. FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  4. FFMPEG视音频编解码零基础学习方法-b

    感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ...

  5. [总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  6. 【转】[总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  7. FFMPEG视音频编解码零基础学习方法 【荐】

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频 编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在 ...

  8. [转载] FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的“大神”,有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然发现了一个问题:在“ ...

  9. EasyDarwin开源音频解码项目EasyAudioDecoder:基于ffmpeg的安卓音频(AAC、G726)解码库(第一部分,ffmpeg-android的编译)

    ffmpeg是一套开源的,完整的流媒体解决方案.基于它可以很轻松构建一些强大的应用程序.对于流媒体这个行业,ffmpeg就像圣经一样的存在.为了表达敬意,在这里把ffmpeg官网的一段简介搬过来,ff ...

随机推荐

  1. CXF总结

    CXF总结 如何来用cxf结合spring开发webservice接口.by@wangkun 下载cxf 下载地址:http://cxf.apache.org/download.html 我下载的版本 ...

  2. python日志,一个改版SMTPHandler

    1.官方logging包的SMTPHandler不支持ssl的邮箱,修改成兼容ssl以支持大部分国内邮箱. 2.增加一个频率控制的参数,比如要设置一个报警邮件,异常时候通知我们,但假设1分钟内异常几千 ...

  3. [JS] ECMAScript 6 - Set & Map : compare with c#

    Ref: Set 和 Map 数据结构 Day 0 - 1所学

  4. "佛祖保佑 永无bug" 注释模板设置详解(仅供娱乐)

    1.注释模板效果图 今天在网上看到一段有趣的注释,佛祖保佑 永无bug, 效果如下图所示:  代码如下所示: /** * _ooOoo_ * o8888888o * 88" . " ...

  5. php-fpm开机自动启动脚本其实源码包里边就有

    网上有各种版本的php-fpm开机自动启动脚本, 其实你编译后源目录已经生成自动脚本.不用做任何修改即用.cp {php-5.5.x-source-dir}/sapi/fpm/init.d.php-f ...

  6. [原]openstack-kilo--issue(二十一) instance can't get ip 虚拟机不能得到ip(2)

    ===问题点==== 在使用vlan模式部署compute节点的时候出现了下面的错误:在controller节点的dhcp-agent.log中 2017-01-22 20:19:34.178 241 ...

  7. jmeter之结果重定向

    在使用jmeter与jenkins对接时,发现默认打印出来的日志就是正常的summary统计,如果要查看日志,只能通过jmeter.log去查看. 来来来,我们一起温习下jmeter的命令行参数 -- ...

  8. Linux学习之---Xshell

    经过两周的断断续续的学习,终于把慕课网上tony老师的<Linux网络管理>基础知识学完.tony老师讲课风趣幽默,深入浅出,为老师打call!! 课程地址:https://www.imo ...

  9. 10.8Xadmin url注册

    2018-10-8 16:45:31 这两天在弄我的服务器,就是是看各种教程 死活部署不好我的Django项目 博客网站 过几天再弄! 越努力,越幸运!永远不要高估自己! 通过两个方法,通过类变量找到 ...

  10. bash 的相关配置

    bash 参数自动补全 请安装 bash-completion bash 提示符 说明:参考文档 1. 简洁风格 if [[ ${EUID} == 0 ]] ; then PS1='\[\033[01 ...