基于FFMPEG的音频解码器

USB中的数据,是通过解码模块之后,将PCM数据存放在FIFO中,再去写再播放出去。具体的数据流向图如下:
这里写图片描述
因为USB中的音频解码出来的PCM数据格式各不相同,为得到相同格式的PCM数据,故需要PCM重采样,将原始PCM数据,转换为双声道32位48KHz的PCM数据。

具体的程序流程如下图所示:其中蓝色部分为UDP输出的过程,浅绿色为解码过程,棕色为重采样过程。
这里写图片描述
这里写图片描述
简单介绍下流程中各函数意义:
av_register_all():注册FFmpeg所有编解码器。
avformat_ network_init():注册FFmpeg所有网络协议。(如果没有,不能udp、rtmp等输出)
avformat_alloc_output_context2():初始化输出码流的AVFormatContext。
avio_open():打开输出文件。
av_new_stream():创建输出码流的AVStream。
avcodec_find_decoder():查找解码器。
avcodec_open2():打开解码器。
avformat_write_header():写文件头(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。
av_read_frame ():将USB的文件,按帧读取。
avcodec_decode_audio4():将包的数据解码成Pframe
swr_convert ():PCM重采样。即将解码后的PCM数据重采样。
av_write_trailer():写文件尾(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。
代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <string.h>
#include "libavformat/avformat.h"
#include "libavutil/mathematics.h"
#include "libavutil/audio_fifo.h"
#include "libswscale/swscale.h"
#include "libavfilter/avfilter.h"
#include "libswresample/swresample.h"
#include "AppGlobal.h"
#include "pelog.h"
#include "ram.h"
#include "block.h"
#include "FPGA.h"
#include "playlist.h"
#include "WSInterface.h"
//#include "block.h"

#define SWR_CH_MAX 32
#define MAX_BUFFER_SIZE 0x100000
#define SWR_SAMPLE_RATE 48000

#define DEBUG_DECODER_FIFO
//#define DEBUG_FFMPEG_FIFO
//#define DEBUG_DECODER_PCM

extern U32 g_PlayProgramID;
extern bool g_USBBlocked;
extern bool g_USBEnd;
extern bool g_USBExit;
extern pthread_t                g_decoder_thread;
extern pthread_mutex_t          g_decoder_pthread_mutex;
extern pthread_cond_t           g_decoder_pthread_cond;
extern PCM_OutputMode g_curOutputMode;
extern char g_heartbeat_status[30];


pthread_t           g_ram_write_thread;
pthread_mutex_t     g_udpout_mutex;
bool      ram_thread_end = false;

/*****************************************************************************
  Function:     UDP_Lock_Init
  Description:  UDP Lock init
  Input:        none
  Output:       none
  Return:       none
  Author:       ruibin.zhang
*****************************************************************************/
void UDP_Lock_Init()
{
    pthread_mutex_init(&g_udpout_mutex, NULL);
}

/*****************************************************************************
  Function:     REG_Lock
  Description:  Lock UDP out
  Input:        none
  Output:       none
  Return:       none
  Author:       ruibin.zhang
*****************************************************************************/
void UDP_Lock()
{
    pthread_mutex_lock(&g_udpout_mutex);
}

/*****************************************************************************
  Function:     UDP_UnLock
  Description:  unLock UDP out
  Input:        none
  Output:       none
  Return:       none
  Author:       ruibin.zhang
*****************************************************************************/
void UDP_UnLock()
{
    pthread_mutex_unlock(&g_udpout_mutex);
}

void get_MacAddr(char *Mac, S32 MacLen, char *EthType)
{
    if(!Mac || !EthType)
    {
        return ;
    }

    S32 s32Macfd = 0;
    struct ifreq Macreq;

    s32Macfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(s32Macfd < 0)
    {
        close(s32Macfd);
        printf("build socket fail\n");
        return ;
    }

    strcpy(Macreq.ifr_name, EthType);

    if(ioctl(s32Macfd, SIOCGIFHWADDR, &Macreq) < 0)
    {
        close(s32Macfd);
        printf("ioctl error\n");
        return ;
    }
    close(s32Macfd);

    snprintf(Mac,  MacLen,  "%02x:%02x:%02x:%02x:%02x:%02x",
        Macreq.ifr_hwaddr.sa_data[0],Macreq.ifr_hwaddr.sa_data[1],
        Macreq.ifr_hwaddr.sa_data[2],Macreq.ifr_hwaddr.sa_data[3],
        Macreq.ifr_hwaddr.sa_data[4],Macreq.ifr_hwaddr.sa_data[5]);
}
/****************************************************************************
 *
 * NAME
 *      peErrCode swr_config(struct SwrContext *s, AVFormatContext *ic, S32 stream_index)
 *
 * PURPOSE:
 *      config swr
 *
 * USAGE
 *      ic->stream[stream_index]->codec is source pcm format
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值