前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >音视频技术(4)-SDL播放PCM

音视频技术(4)-SDL播放PCM

作者头像
公号sumsmile
发布2020-03-27 12:27:12
8910
发布2020-03-27 12:27:12
举报

SDL 是一套跨平台的音视频播放框架,对齐了底层硬件的差异,开发者可以专注于音视频的处理,本文记录在iOS上使用SDL播放pcm音频裸数据的实现过程。pcm是音频的裸数据。

  1. sdl编译:可以直接在sdl官网下载源码编译成iOS平台使用的.a静态库,编译方式有两种,1)xcode编译;2)shell脚本编译,详细可以参考源码里的readme文档 源码目录:

image.png

用sh脚本编译的.a文件,最后运行不过去,会报错,在sdl论坛里提问了,也没有人回答,建议用第一种方式编译,笔者在学习的过程中节省时间,直接扣了别人已经编译好的.a文件

  1. 集成:1)copy 头文件到工程目录下,2) 添加库引用,参考如下库引用,可能有用不到的

image.png

  1. 代码编写,代码不多,100行左右即可实现,核心代码实现如下

执行流程: 初始化SDL --> 打开pcm文件-->调用SDL播放-->SDL回调里取每一帧的播放数据-->当前线程等待pcm播放完,然后再去取下一个缓存的数据

代码语言:javascript
复制
#import "AudioPlayerSDL2.h"

static Uint32 audio_len;
static Uint8 *audio_pos;

void fill_audio(void *udata, Uint8 *stream, int len){
    SDL_memset(stream, 0, len);
    if(audio_len == 0){
        return;
    }

    len = (len > audio_len? audio_len : len);
    printf("audio %d %d \n", audio_len, len);
    SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);
    audio_pos += len;
    audio_len -= len;
}

 int cppTest(){
    SDL_SetMainReady();
    
    if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER)){
        printf("Could not initialize SDL -%s\n", SDL_GetError());
        return -1;
    }
    
    SDL_AudioSpec wanted_spec;
    wanted_spec.freq = 44100;
    wanted_spec.format = AUDIO_S16SYS;
    wanted_spec.channels = 2;
    wanted_spec.silence = 0;
    wanted_spec.samples = 1024;
    wanted_spec.callback = fill_audio;
    
    if (SDL_OpenAudio(&wanted_spec, NULL) < 0){
        printf("can't open audio.\n");
        return -1;
    }
    
    NSString *pcmdir = [NSString stringWithFormat:@"resource.bundle/test1.pcm"];
    
    NSString *ppth = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:pcmdir];
    FILE *fp = fopen([ppth UTF8String], "r");
    
    if(fp == NULL){
        printf("cannot open this file\n");
        return -1;
    } else {
        printf("open file :%s", [pcmdir UTF8String]);
    }
    
    int pcm_buffer_size = 4096;
    char *pcm_buffer = (char *)malloc(pcm_buffer_size);
    int data_count = 0;
    SDL_PauseAudio(0);

    while (1) {
        if(fread(pcm_buffer, 1, pcm_buffer_size, fp) != pcm_buffer_size){
//            fseek(fp, 0, SEEK_SET);
//            fread(pcm_buffer, 1, pcm_buffer_size, fp);
//            data_count = 0;
            break;
        }
        
        printf("Now Playing %10d Bytes data.\n", data_count);
        data_count += pcm_buffer_size;
        
        audio_len = pcm_buffer_size;
        audio_pos = (Uint8 *) pcm_buffer;
        
//        SDL_PauseAudio(0);
        while (audio_len > 0) {
            SDL_Delay(1);
        }
    }
     if(pcm_buffer){
         free(pcm_buffer);
     }
     
    fclose(fp);
     SDL_Quit();

    return 0;
}

使用ffmpeg从mp4中提取pcm文件 提取:ffmpeg -i 1.mp4 -vn -ar 44100 -ac 2 -f s16le out.pcm 播放:ffplay -ac 2 -ar 44100 -f s16le out.pcm

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档