没办法,工作中遇到了问题。

目前NEC EMMA的架构如下:

从USB读入文件 -> 文件分析并提取Packet中的Payload Data   -> NEC HANDLE AVTransfer  -> NEC HANDLE WMV -> AUDIO OUTPUT

按照驱动的API写好代码后却怎么也没有声音,所有API返回值均OK。

郁闷开始了。继续绝望中寻找希望。

为了对比调试,参考

http://blog.csdn.net/ashlingr/article/details/7791321

并做了一些ffmpeg版本升级修改。

修改前:

  1. len = avcodec_decode_audio (pAudioCodecCtx,
  2. (int16_t *)decompressed_audio_buf,
  3. &decompressed_audio_buf_size,        // it is the decompressed frame in BYTES 解码后的数据大小,字节为单位;
  4. packet.data,
  5. packet.size );

修改后:

decompressed_audio_buf_size = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2; // 不加这一行,执行时会出错。

len = avcodec_decode_audio3 (pCodecCtx,

(int16_t *)decompressed_audio_buf,

&decompressed_audio_buf_size,        // it is the decompressed frame in BYTES

&packet);

遇到的问题:

/dev/dsp 设备不存在

解决办法:

modprobe snd_pcm_oss  (需要su到root用户)

完整代码如下:(基本来自http://bbs.chinavideo.org/viewthread.php?tid=1247&extra=page%3D1

#include <avcodec.h> 
#include <avformat.h> 
#include <avutil.h> 
#include <assert.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <X11/Xlib.h> 
#include <sys/soundcard.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <sys/ioctl.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sched.h>

#define ALL_DEBUG

#ifdef ALL_DEBUG 
    #define AV_DEBUG 
    #define AUDIO_DEBUG 
#endif

//------------------------------------------------------------------------------ 
// manipulations for file 
int open_file (char *file_name, int mode) 

    // open file file_name and return the file descriptor; 
    int fd;

if ((fd = open (file_name, mode)) < 0) 
    { 
        fprintf (stderr, " Can't open %s!/n", file_name); 
        exit (-1); 
    } 
    return fd; 
}

int set_audio (int fd, AVCodecContext * pCodecCtx) 

    // set the properties of audio device with pCodecCtx;

int i, err; 
    /* 设置适当的参数,使得声音设备工作正常 */ 
    /* 详细情况请参考Linux关于声卡编程的文档 */ 
   
    i = 0; 
    ioctl (fd, SNDCTL_DSP_RESET, &i); 
    i = 0; 
    ioctl (fd, SNDCTL_DSP_SYNC, &i); 
    i = 1; 
    ioctl (fd, SNDCTL_DSP_NONBLOCK, &i); 
   
    // set sample rate; 
    #ifdef AUDIO_DEBUG 
    printf ("pCodecCtx->sample_rate:%d/n", pCodecCtx->sample_rate); 
    #endif 
    i = pCodecCtx->sample_rate; 
    if (ioctl (fd, SNDCTL_DSP_SPEED, &i) == -1) 
    { 
        fprintf (stderr, "Set speed to %d failed:%s/n", i, 
             strerror (errno)); 
        return (-1); 
    } 
    if (i != pCodecCtx->sample_rate) 
    { 
        fprintf (stderr, "do not support speed %d,supported is %d/n", 
             pCodecCtx->sample_rate, i); 
        return (-1); 
    } 
   
    // set channels; 
    i = pCodecCtx->channels; 
    #ifdef AUDIO_DEBUG 
    printf ("pCodecCtx->channels:%d/n", pCodecCtx->channels); 
    #endif 
    if ((ioctl (fd, SNDCTL_DSP_CHANNELS, &i)) == -1) 
    { 
        fprintf (stderr, "Set Audio Channels %d failed:%s/n", i, 
             strerror (errno)); 
        return (-1); 
    } 
    if (i != pCodecCtx->channels) 
    { 
        fprintf (stderr, "do not support channel %d,supported %d/n", 
            pCodecCtx->channels, i); 
        return (-1); 
    } 
    // set bit format; 
    i = AFMT_S16_LE; 
    if (ioctl (fd, SNDCTL_DSP_SETFMT, &i) == -1) 
    { 
        fprintf (stderr, "Set fmt to bit %d failed:%s/n", i, 
             strerror (errno)); 
        return (-1); 
    } 
    if (i != AFMT_S16_LE) 
    { 
        fprintf (stderr, "do not support bit %d, supported %d/n", 
             AFMT_S16_LE, i); 
        return (-1); 
    } 
   
    // set application buffer size; 
    // i = (0x00032 << 16) + 0x000c;        // 32 4kb buffer; 
    // ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &i); 
    i = 1; 
    ioctl (fd, SNDCTL_DSP_PROFILE, &i); 
   
    return 0; 
}

void close_file (int fd) 

    // close the file pointed by file descriptor fd; 
    close (fd); 
}

//------------------------------------------------------------------------------ 
// handle audio;

void display_AVCodecContext(AVCodecContext *pCodecCtx){ 
    // 
    #define STDOUT stderr 
    fprintf(STDOUT, "pCodecCtx->bit_rate:%d/n", pCodecCtx->bit_rate); 
    fprintf(STDOUT, "pCodecCtx->sample_rate:%d/n", pCodecCtx->sample_rate); 
    fprintf(STDOUT, "pCodecCtx->channels:%d/n", pCodecCtx->channels); 
    fprintf(STDOUT, "pCodecCtx->frame_size:%d/n", pCodecCtx->frame_size); 
    fprintf(STDOUT, "pCodecCtx->frame_number:%d/n", pCodecCtx->frame_number); 
    fprintf(STDOUT, "pCodecCtx->delay:%d/n", pCodecCtx->delay); 
    fprintf(STDOUT, "pCodecCtx->frame_bits:%d/n", pCodecCtx->frame_bits); 
}

// error if return -1; 
// success if return 0; 
// 这里要用到指向指针的指针,否则传不到值; 
int av_init (char *file_name, AVFormatContext ** pFormatCtx, 
     AVCodecContext ** pCodecCtx, int *p_audioStream) 

    // init the codec and format of input file file_name; 
    int audioStream, i; 
    AVCodec *pCodec; 
    // catch error 
    assert(file_name != NULL); 
    assert(*pFormatCtx != NULL); 
    assert(*pCodecCtx != NULL); 
   
    // Register all formats and codecs 
    av_register_all (); 
   
    // open file 
    if (av_open_input_file (pFormatCtx, file_name, NULL, 0, NULL) != 0){ 
        // Couldn't open file 
        fprintf (stderr, " Can't open %s!/n", file_name); 
        return -1;   
    }

// Retrieve stream information 
    if (av_find_stream_info (*pFormatCtx) < 0){ 
        // Couldn't find stream information 
        return -1;   
    } 
   
    #ifdef AV_DEBUG 
    // Dump information about file onto standard error 
    dump_format (*pFormatCtx, 0, file_name, 0); 
    #endif 
   
    // Find the first audio and video stream respectively 
    audioStream = -1; 
    for (i = 0; i < (*pFormatCtx)->nb_streams; i++){ 
        if ((*pFormatCtx)->streams[i]->codec->codec_type == 
            AVMEDIA_TYPE_AUDIO) 
        { 
            audioStream = i; 
        } 
    } 
   
    #ifdef AV_DEBUG 
    // dump_stream_info(pFormatCtx); 
    #endif 
   
    // exclude error 
    if (audioStream == -1){ 
        // Didn't find a audio or video stream 
        return -1;   
    }

// Get a pointer to the codec context for the audio stream 
    *pCodecCtx = (*pFormatCtx)->streams[audioStream]->codec;

// Find the decoder for the audio stream 
    pCodec = avcodec_find_decoder ((*pCodecCtx)->codec_id); 
    if (pCodec == NULL) 
        return -1;    // Codec not found

// Open codec 
    if (avcodec_open ((*pCodecCtx), pCodec) < 0){ 
        return -1;    // Could not open codec 
    } 
   
    #ifdef AUDIO_DEBUG 
    // printf ("pCodecCtx->sample_rate:%d, audioStream:%d/n", (*pCodecCtx)->sample_rate, audioStream); 
    // display_AVCodecContext(*pCodecCtx); 
    #endif 
   
    *p_audioStream = audioStream; 
   
    return 0; 
}

void av_play (AVFormatContext * pFormatCtx, 
     AVCodecContext * pCodecCtx, int audioStream) 

    // which was read from one frame; 
    AVPacket packet; 
    uint32_t len; 
    uint8_t decompressed_audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2]; 
    int decompressed_audio_buf_size; 
    uint8_t * p_decompressed_audio_buf; 
    int fd = -1;    // audio file or test file? 
    char filename[64] = "/dev/dsp"; 
    int mode = O_WRONLY; 
    // 
   
    // open audio file or written file 
    // printf("fd:%d", fd); 
    fd = open_file(filename, mode); 
    printf("fd:%d \n", fd); 
    // 
    set_audio(fd, pCodecCtx); 
   
    // 
    printf("(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2=%d\n", (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2); 
    printf("AVCODEC_MAX_AUDIO_FRAME_SIZE=%d\n", AVCODEC_MAX_AUDIO_FRAME_SIZE); 
   
    // for a test 
    // char test_file[256] = "my_pcm.pcm"; 
    // fd = open_file(test_file, mode); 
   
    #ifdef AV_DEBUG 
    static int size = 0; 
    #endif 
    // 
   
    // set the sched priority 
    // 这是为了提高音频优先级;不晓得起作用没; 
    int policy = SCHED_FIFO; 
    sched_setscheduler(0, policy, NULL); 
   
    int write_buf_size = 4196; 
    int written_size; 
    while (av_read_frame (pFormatCtx, &packet) >= 0) 
    { 
        // Is this a packet from the audio stream? 
        // 判断是否音频帧; 
        if (packet.stream_index == audioStream) 
        { 
            // Decode audio frame 
            // 解码音频数据为pcm数据; 
            decompressed_audio_buf_size = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2;
            len = avcodec_decode_audio3 (pCodecCtx, 
                            (int16_t *)decompressed_audio_buf, 
                            &decompressed_audio_buf_size,        // it is the decompressed frame in BYTES 
                            &packet); 
            // printf("len:%d, packet.size:%d/n", len, packet.size); 
            if ( len < 0 ){ 
                // if error len = -1 
                printf("+----- error in decoding audio frame\n"); 
                // exit(0); 
            } 
            // test lsosa 
           
           
            // printf("size = %d/n", size); 
            //****************************************************************** 
            // 重点是这一部分,使用oss播放的代码,之前的数据写是否完整的问题就是出在这里,或者是前面的set_audio函数设置不正确; 
            // audio_buf_info info; 
            p_decompressed_audio_buf = decompressed_audio_buf; 
            while ( decompressed_audio_buf_size > 0 ){ 
                // 解码后数据不为零,则播放之,为零,则; 
                written_size = write(fd, p_decompressed_audio_buf, decompressed_audio_buf_size); 
                if ( written_size == -1 ){ 
                    // printf("error:decompressed_audio_buf_size:%d, decompressed_audio_buf_size:%d, %s/n", / 
                    //            decompressed_audio_buf_size, decompressed_audio_buf_size,strerror(errno)); 
                    // usleep(100); 
                    continue; 
                } 
                // printf("decompressed_audio_buf_size:%d, written_size:%d/n", / 
                //           decompressed_audio_buf_size, written_size); 
                decompressed_audio_buf_size -= written_size; 
                p_decompressed_audio_buf += written_size; 
               
            }// end while 
            //****************************************************************** 
        } 
        else 
        { 
            printf("+----- this is not audio frame/n"); 
        }// end if 
        // Free the packet that was allocated by av_read_frame 
        av_free_packet (&packet); 
    }// end while of reading one frame; 
       
    close_file(fd); 
}

void av_close (AVFormatContext * pFormatCtx, AVCodecContext * pCodecCtx) 

    // close the file and codec

// Close the codec 
    avcodec_close (pCodecCtx);

// Close the video file 
    av_close_input_file (pFormatCtx); 
}

//------------------------------------------------------------------------------

int main (int argc, char **argv){ 
    // 
    AVFormatContext *pFormatCtx; 
    int audioStream = -1; 
    AVCodecContext *pCodecCtx; 
   
    // exclude the error about args; 
    if ( argc != 2 ){ 
        printf("please give a file name\n"); 
        exit(0); 
    } 
   
    // 注意:这里要用到指向指针的指针,是因为这个初始化函数需要对指针的地址进行改动, 
    // 所以,只有这么做,才能达到目的; 
    if ( av_init(argv[1], &pFormatCtx, &pCodecCtx, &audioStream) < 0 ){ 
        // 
        fprintf(stderr, "error when av_init\n"); 
    } 
   
    // play the audio file 
    av_play(pFormatCtx, pCodecCtx, audioStream); 
   
    // close all the opend files 
    av_close(pFormatCtx, pCodecCtx); 
   
}

ffmpeg + sdl -03 简单音频播放器实现的更多相关文章

  1. ffmpeg+SDL2实现的音频播放器V2.0(无杂音)

    1. 前言 目前为止,学习了并记录了ffmpeg+SDL2显示视频以及事件(event)的内容. 这篇中记录ffmpeg+SDL2播放音频,没加入事件处理. 接下来加入事件处理并继续学习音视频同步,再 ...

  2. IOS开发之简单音频播放器

    今天第一次接触IOS开发的UI部分,之前学OC的时候一直在模拟的使用Target-Action回调模式,今天算是真正的用了一次.为了熟悉一下基本控件的使用方法,和UI部分的回调,下面开发了一个特别简易 ...

  3. WIN32下使用DirectSound接口的简单音频播放器(支持wav和mp3)

    刚好最近接触了一些DirectSound,就写了一个小程序练练手,可以用来添加播放基本的wav和mp3音频文件的播放器.界面只是简单的GDI,dxsdk只使用了DirectSound8相关的接口. D ...

  4. 最简单的基于FFMPEG+SDL的音频播放器 ver2 (采用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  5. 最简单的基于FFMPEG+SDL的音频播放器 ver2 (採用SDL2.0)

    ===================================================== 最简单的基于FFmpeg的音频播放器系列文章列表: <最简单的基于FFMPEG+SDL ...

  6. H.264:FFMpeg 实现简单的播放器

    H.264:FFMpeg 实现简单的播放器   FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手.我刚接触FFMPEG的时候也感觉不知从何学起. 因此我 ...

  7. [SimplePlayer] 实现一个简单的播放器

    简单的播放器需要实现一个最基本的功能:播放视频文件. 实现这个功能需要包含以下几个步骤: 从视频文件中提取视频图像 在屏幕上显示视频图像 视频帧的同步,也就是保证视频图像在合适的时间在屏幕上显示 从视 ...

  8. 11.QT-ffmpeg+QAudioOutput实现音频播放器

    1.前言      由于QAudioOutput支持的输入数据必须是原始数据,所以播放mp3,WAV,AAC等格式文件,需要解封装后才能支持播放.      而在QT中,提供了QMediaPlayer ...

  9. Android 实现简单音乐播放器(二)

    在Android 实现简单音乐播放器(一)中,我介绍了MusicPlayer的页面设计. 现在,我简单总结一些功能实现过程中的要点和有趣的细节,结合MainActivity.java代码进行说明(写出 ...

随机推荐

  1. android 判断是否有sim卡及运营商

    判断是否有sim卡的方法:   int absent = TelephonyManager.SIM_STATE_ABSENT; if (1 == absent) { Log.d(TAG,"请 ...

  2. HDU 1853Cyclic Tour(网络流之最小费用流)

    题目地址:pid=1853">HDU1853 费用流果然好奇妙. .还能够用来推断环...假设每一个点都是环的一部分并且每一个点仅仅能用到一次的话,那每一个点的初度入度都是1,这就能够 ...

  3. 如何使用easyUI

    一.简介 以下内容来自百度: jQuery EasyUI是一组基于jQuery的UI插件集合,而jQuery EasyUI的 目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面.开发者不 ...

  4. 2:numpy---ndarray

    ndarray即是多维数组[n dimension array] 一:创建ndarray 有好几种创建数组的方法. 例如,你可以使用 array 函数从常规的Python列表和元组创造数组.所创建的数 ...

  5. _CrtMemBlockHeader

    typedef struct _CrtMemBlockHeader{// Pointer to the block allocated just before this one:struct _Crt ...

  6. PHP扩展开发(3)-config.m4

    1. 宏命令 1.1. dnl 注释      1.2. 扩展的工作方式           1.2.1) PHP_ARG_WITH不需要第三方库           1.2.2) PHP_ARG_E ...

  7. php提取身份证号码中的生日日期以及验证是否为未成年人的函数

    php 提取身份证号码中的生日日期以及确定是否成年的一个函数.可以同时确定15位和18位的身份证,经本人亲测,非常好用,分享函数代码如下: <?php //用php从身份证中提取生日,包括15位 ...

  8. R语言学习网站

    一个不错的个人R语言博客网站 http://blog.fens.me/r-overview/

  9. C#文本文件导入数据库

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windo ...

  10. FLASH驱动之-块设备驱动系统构架

    一.  块设备是只能以块为单位进行访问的设备,块的大小一般是512个字节的整数倍,常见的块设备包括硬件,SD卡,光盘,flash等.驱动程序是块的整数倍从设备读写得到数据.块设备的最小访单位为块,不同 ...