2015/11/13

pcm_write

tinyalsa 的 pcm_write:
static int pcm_write_wrapper(struct pcm *pcm, const void * buffer, size_t bytes, int flags)
{
    int ret = 0;
    if(flags & PCM_MMAP)
         ret = pcm_mmap_write(pcm, (void *)buffer, bytes);
    else
         ret = pcm_write(pcm, (void *)buffer, bytes);
一般都沒有用 MMAP.
所以都是直接 call pcm_write( )

tinyalsa 實做的 pcm_write( ) 就是用for loop 把 buffer 一一寫入 ioctl:
    struct snd_xferi x;

    x.buf = (void*)data;
    x.frames = count / (pcm->config.channels *
                        pcm_format_to_bits(pcm->config.format) / 8);

    ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))

這樣就進入 kernel 了..

kernel 的 snd_pcm_playback_ioctl1 呼叫 snd_pcm_lib_write 來做:
static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
                                      unsigned int hwoff,
                                      unsigned long data, unsigned int off,
                                      snd_pcm_uframes_t frames)
{
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
        char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);

        if (substream->ops->copy) {
                if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
                        return err;
        } else {
                char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
                if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
                        return -EFAULT;
        }
        return 0;
}



錯了。結果是用 MMAP...
所以,trace 到最後,是 call kernel 的 snd_pcm_sync_ptr..

修改一下 hardware/imx/alsa/tinyalsa_hal.c, 拿掉 MMAP, 就會 call pcm_write(), 就可以換掉 pcm_write 了..
diff --git a/alsa/tinyalsa_hal.c b/alsa/tinyalsa_hal.c
index a4644ac..2b85b88 100644
--- a/alsa/tinyalsa_hal.c
+++ b/alsa/tinyalsa_hal.c
@@ -16,7 +16,7 @@
/* Copyright (C) 2012-2015 Freescale Semiconductor, Inc. */
#define LOG_TAG "audio_hw_primary"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#include <errno.h>
#include <pthread.h>
@@ -524,7 +524,7 @@ static int start_output_stream_primary(struct imx_stream_out *out)
pcm_device = out->device & (AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_AUX_DIGITAL);
if (pcm_device && (adev->active_output[OUTPUT_ESAI] == NULL || adev->active_output[OUTPUT_ESAI]->standby)) {
- out->write_flags[PCM_NORMAL] = PCM_OUT | PCM_MMAP | PCM_MONOTONIC;
+ out->write_flags[PCM_NORMAL] = PCM_OUT | PCM_MONOTONIC;
out->write_threshold[PCM_NORMAL] = PLAYBACK_LONG_PERIOD_COUNT * LONG_PERIOD_SIZE;
out->config[PCM_NORMAL] = pcm_config_mm_out;
@@ -1175,6 +1175,27 @@ static int pcm_read_wrapper(struct pcm *pcm, const void * buffer, size_t bytes)
return ret;
}
+static int s_pcm_write(struct pcm *pcm, void * buffer, size_t bytes)
+{
+ int i;
+ unsigned short *dst;
+ unsigned short *src;
+ unsigned short patten = 0x0000;
+ int rc;
+
+ dst = (unsigned short*)malloc(bytes);
+ src = (unsigned short*)buffer;
+
+ for(i=0 ; i<bytes/2 ; i++)
+ dst[i]=src[i];
+
+ rc = pcm_write(pcm, (void*)dst, bytes);
+ free(dst);
+ return rc;
+
+
+}
static int pcm_write_wrapper(struct pcm *pcm, const void * buffer, size_t bytes, int flags)
{
@@ -1182,7 +1203,7 @@ static int pcm_write_wrapper(struct pcm *pcm, const void * buffer, size_t bytes,
if(flags & PCM_MMAP)
ret = pcm_mmap_write(pcm, (void *)buffer, bytes);
else
- ret = pcm_write(pcm, (void *)buffer, bytes);
+ ret = s_pcm_write(pcm, (void *)buffer, bytes);
if(ret !=0) {
ALOGW("ret %d, pcm write %d error %s", ret, bytes, pcm_get_error(pcm));
@@ -1200,7 +1221,7 @@ static int pcm_write_wrapper(struct pcm *pcm, const void * buffer, size_t bytes,
if(flags & PCM_MMAP)
ret = pcm_mmap_write(pcm, (void *)buffer, bytes);
else
- ret = pcm_write(pcm, (void *)buffer, bytes);
+ ret = s_pcm_write(pcm, (void *)buffer, bytes);
}
return ret;
view raw gistfile1.txt hosted with ❤ by GitHub

沒有留言:

張貼留言