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

目前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. springmvc 基础

    在最简单的springmvc应用程序中,控制器是唯一需要在java web部署描述文件(web.xml)中配置的servlete(springmvc的控制器是Dispatcher Servlet).每 ...

  2. 高性能Java Web 页面静态化技术

    package com.yancms.util; import java.io.*; import org.apache.commons.httpclient.*; import org.apache ...

  3. JavaScript原型,原型链 !

    js原型 问题:什么是js原型? js每声明一个function,都有prototype原型,prototype原型是函数的一个默认属性,在函数的创建过程中由js编译器自动添加. 也就是说:当生产一个 ...

  4. c - 比较字符串的大小

    c的标准库中当然有现成的比较字符串的函数<string.h>中的 strcmp int __cdecl strcmp(_In_z_ const char * _Str1, _In_z_ c ...

  5. javascript 倒计时跳转.

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  6. 2016年的个人计划-xiangjiejie

    过去一年,开发了angularjs的wap项目,appwap社区,忙忙碌碌不停的做各种活动. 职业目标 今年,要多看书,别总是被懒癌缠身. 多学习,过去半年很少看技术文章了吧,养成定期看文章的好习惯, ...

  7. 关于curl_setopt参数的记录

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE) 其中true输出执行结果,false为不输出 fsockopen与curl_setopt请求的区别之一就是 ...

  8. 万维网发布服务(w3svc)已停止,除非万维网发布服务(w3svc)正在运行。

    近来遇到一个IIS服务启动问题,重启服务器PC后,网站启动的时候,提示“ 万维网发布服务(w3svc)已停止,除非万维网发布服务(w3svc)正在运行”. 解决方法: 点击"开始" ...

  9. Python学习笔记总结(二)函数和模块

    一.函数 函数的作用:可以计算出一个返回值,最大化代码重用,最小化代码冗余,流程的分解. 1.函数相关的语句和表达式 语句        例子 Calls        myfunc(‘diege', ...

  10. OCR中的倾斜矫正

    电面中被问到了做的LPR,简单的介绍了下后又问到了关于如何矫正倾斜角的问题.答得比较含糊,所以今天来补充一下. 倾斜矫正的方法有很多种,包括基于Hough变换的矫正,基于字符投影的倾角矫正,常规线性角 ...