FFmpeg 裁剪——音频解码

只留下某些音频的配置:

./configure --enable-shared --disable-yasm --enable-memalign-hack --enable-gpl --enable-cross-compile --prefix=/home/liqinghan/workspace/ffmpeg-3.2.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);
#endif


内部实现:

 

 

#include "config.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


#include "libavutil/internal.h"
#include "libavcodec/avcodec.h"
#include "avaudiodecoder.h"

#if HAVE_SYS_RESOURCE_H
#include 
#include 
#include 
#elif HAVE_GETPROCESSTIMES
#include 
#endif
#if HAVE_GETPROCESSMEMORYINFO
#include 
#include 
#endif
#if HAVE_SETCONSOLECTRLHANDLER
#include 
#endif


#if HAVE_SYS_SELECT_H
#include 
#endif

#if HAVE_TERMIOS_H
#include 
#include 
#include 
#include 
#elif HAVE_KBHIT
#include 
#endif

#if HAVE_PTHREADS
#include 
#endif

#include 

#define _AV_AUDIO_DECODER_DEBUG_(fmt,args...) \
	do{ \
		printf("[av_audio_decoder_debug]");\
		printf(fmt,##args); \
	}while(0)

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 = 0;

#pragma pack(push) 
#pragma pack(1)
//共享内存区!
typedef struct{
	int writeable;
	int memsize;
	int bufsize;
	int64_t pts;
	char buf[0]; //定义一个不占为位置的符号,数据的起始地址
}AVshareMemBuf;

#pragma pack(pop) 

static AVshareMemBuf* outMemBuf;
static AVshareMemBuf* userBuf;

static void* shmembuf;

static pthread_t pid;

static int getframectrl = 0;

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*1000*1000;
	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, 0, 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        = 0;
    frame->pkt_pos             = -1;
    frame->pkt_size            = -1;
    frame->key_frame           = 1;
    frame->sample_aspect_ratio = (AVRational){ 0, 1 };
    frame->format              = -1; /* 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               = 0;
}

static void audio_decoder_vb_destroy(void){ 
	
	shmdt(shmembuf);
	vb_initialized = 0;
	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 | 0666);

	//第二个参数shmaddr为NULL,内核会自动选择地址映射
	shmembuf = shmat(shmid, NULL, 0);
	
	userBuf = (AVshareMemBuf*)shmembuf; 
	userBuf->writeable = 1;
	userBuf ->size = frmSize;
	av_init_packet(&avPkt);
	vb_initialized = 1;
}

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 -1;
	}
	//给解码器申请上下文,就是处理空间
	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 < 0 ) 
	{	
		avcodec_free_context(&codecContext);

		_AV_AUDIO_DECODER_DEBUG_("can not open codec\n");

		return -1;
	}
	audioSize = decoderAttr.num_point_per_pack;

	outMemBuf =(AVshareMemBuf*)malloc(sizeof(AVshareMemBuf) + audioSize);
	outMemBuf->size = audioSize;
	outMemBuf->writeable =1;

	pthread_mutex_init (&mutex,NULL);
	//创建VB
    audio_decoder_vb_create(decoderAttr.frmsize);

	return 0;

	
}

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, 0) == -1)
	{
		_AV_AUDIO_DECODER_DEBUG_("shmctl(IPC_RMID) failed\n");
			//exit(EXIT_FAILURE);
	}  

	return 0;
}

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 -1;}

	
	
	if(collision < 0){

		while(userBuf->writeable == 0){
			
		}
		
	}
	else if(collision ==0){

		if(userBuf->writeable == 0) {
			
			_AV_AUDIO_DECODER_DEBUG_("decoder buffer is full\n");
			return -1;
		}
	}
	else{
		
		uint64_t time = get_cur_time();
		
		while(userBuf->writeable == 0){

			if((get_cur_time() - time) > collision) {

				_AV_AUDIO_DECODER_DEBUG_("decoder buffer is full\n");
			
				return -1;
			}
		}

	}

	if(userBuf->size < size){
	
		_AV_AUDIO_DECODER_DEBUG_("userBuf->size:%d,size:%d,frame size is too larger\n",userBuf->size,size);
		
		return -1;
	}

	memcpy(userBuf->buf,packet,size);
	
	userBuf->writeable = 0;
	userBuf->pts = pts;
	userBuf->size = size;
	
	return 0;
	
}

int audio_send_packet_stop(void){

	audio_decoder_vb_destroy();

}


void audio_decode_start(void){

	if(getframectrl) return;
	
	getframectrl =1;
	
	pthread_create(&pid,NULL,audio_decode_start_thread,NULL);
	
}

void audio_decode_stop(void){

	if(getframectrl ==0) return;
	
	getframectrl =0;
	
	pthread_join(pid,NULL);
	
}

void* audio_decode_start_thread(void* param){
	
	int got_frame = 0;
	
	AVshareMemBuf* membuf = NULL;


	membuf = (AVshareMemBuf*)malloc(sizeof(AVshareMemBuf) + userBuf->size);

	while(getframectrl){

		if(userBuf->writeable == 0){

			membuf->pts = userBuf->pts;
			membuf->size = userBuf->size;
			memcpy(membuf->buf,userBuf->buf,membuf->size);
			userBuf->writeable = 1;
			
			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 0;
				}
			}
		
			else{
				audio_get_frame_defaults(decodedFrame);
			}
			
			got_frame = 0 ;

			int len = avcodec_decode_audio4(codecContext, decodedFrame, &got_frame, &avPkt);
			
			
			if (len < 0) 
			{
				// 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, 1);
		
				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[0],data_size);
		
						outMemBuf->writeable = 0;
						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 =-1;
	pthread_mutex_lock(&mutex);
	if(outMemBuf->writeable == 0){
		
		memcpy(buf,outMemBuf->buf,outMemBuf->size);
		*pts = outMemBuf->pts;
		*size = outMemBuf->size;
		outMemBuf->writeable = 1;
		ret = 0;
	}
	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 := avaudiodecoder.so
ALIB := avaudiodecoder.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
#hisi3536lib#########
INC_FLAGS += -I..
#-g加上调试增加数据量,应该去掉
CFLAGS := -Wall -g -shared  -fPIC   
LD_FLAGS =  -lpthread -lm -ldl
TCLLIB = $(SOLIB) $(ALIB)

all: $(TCLLIB)
%.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


 

 

 

 

 

你可能感兴趣的:(gcc,流媒体,armlinux)