nxplayer: add mp3 offload playback demo
Mask: Only parse ID3v2 header simple. Usage: nxplayer device pcm0p play /stream/1.mp3 Signed-off-by: qiaohaijiao1 <qiaohaijiao1@xiaomi.com>
This commit is contained in:
parent
5ae46ab6a7
commit
05eadd1bd6
@ -39,6 +39,14 @@
|
||||
* Public Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
struct nxplayer_dec_ops_s
|
||||
{
|
||||
int format;
|
||||
CODE int (*pre_parse)(int fd, FAR uint32_t *samplerate,
|
||||
FAR uint8_t *chans, FAR uint8_t *bps);
|
||||
CODE int (*fill_data)(int fd, FAR struct ap_buffer_s *apb);
|
||||
};
|
||||
|
||||
/* This structure describes the internal state of the NxPlayer */
|
||||
|
||||
struct nxplayer_s
|
||||
@ -72,6 +80,8 @@ struct nxplayer_s
|
||||
uint16_t treble; /* Treble as a whole % */
|
||||
uint16_t bass; /* Bass as a whole % */
|
||||
#endif
|
||||
|
||||
FAR const struct nxplayer_dec_ops_s *ops;
|
||||
};
|
||||
|
||||
typedef int (*nxplayer_func)(FAR struct nxplayer_s *pplayer, char *pargs);
|
||||
@ -480,6 +490,53 @@ int nxplayer_settreble(FAR struct nxplayer_s *pplayer, uint8_t treble);
|
||||
int nxplayer_systemreset(FAR struct nxplayer_s *pplayer);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxplayer_parse_mp3
|
||||
*
|
||||
* Performs pre-process when play mp3 file.
|
||||
* Parse samplerate, channels, bps.
|
||||
*
|
||||
* Input Parameters:
|
||||
* pplayer - Pointer to the context to initialize
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if file parsed successfully.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxplayer_parse_mp3(int fd, FAR uint32_t *samplerate,
|
||||
FAR uint8_t *chans, FAR uint8_t *bps);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxplayer_fill_mp3
|
||||
*
|
||||
* Performs read mp3 frame to apb buffer
|
||||
*
|
||||
* Input Parameters:
|
||||
* pplayer - Pointer to the context to initialize
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if file read successfully.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxplayer_fill_mp3(int fd, FAR struct ap_buffer_s *apb);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxplayer_fill_pcm
|
||||
*
|
||||
* Performs read pcm file to apb buffer
|
||||
*
|
||||
* Input Parameters:
|
||||
* pplayer - Pointer to the context to initialize
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if file read successfully.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxplayer_fill_pcm(int fd, FAR struct ap_buffer_s *apb);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ include $(APPDIR)/Make.defs
|
||||
# NxPlayer Library
|
||||
|
||||
CSRCS = nxplayer.c
|
||||
CSRCS += nxplayer_mp3.c
|
||||
CSRCS += nxplayer_pcm.c
|
||||
|
||||
ifneq ($(CONFIG_NXPLAYER_COMMAND_LINE),)
|
||||
PROGNAME = nxplayer
|
||||
|
@ -88,6 +88,10 @@ struct nxplayer_ext_fmt_s
|
||||
int nxplayer_getmidisubformat(int fd);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIO_FORMAT_MP3
|
||||
int nxplayer_getmp3subformat(int fd);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
@ -99,7 +103,7 @@ static const struct nxplayer_ext_fmt_s g_known_ext[] =
|
||||
{ "ac3", AUDIO_FMT_AC3, NULL },
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_FORMAT_MP3
|
||||
{ "mp3", AUDIO_FMT_MP3, NULL },
|
||||
{ "mp3", AUDIO_FMT_MP3, nxplayer_getmp3subformat },
|
||||
#endif
|
||||
#ifdef CONFIG_AUDIO_FORMAT_DTS
|
||||
{ "dts", AUDIO_FMT_DTS, NULL },
|
||||
@ -121,6 +125,21 @@ static const struct nxplayer_ext_fmt_s g_known_ext[] =
|
||||
|
||||
static const int g_known_ext_count = sizeof(g_known_ext) /
|
||||
sizeof(struct nxplayer_ext_fmt_s);
|
||||
|
||||
static const struct nxplayer_dec_ops_s g_dec_ops[] =
|
||||
{
|
||||
{
|
||||
AUDIO_FMT_MP3,
|
||||
nxplayer_parse_mp3,
|
||||
nxplayer_fill_mp3
|
||||
},
|
||||
{
|
||||
AUDIO_FMT_PCM,
|
||||
NULL,
|
||||
nxplayer_fill_pcm
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* CONFIG_NXPLAYER_FMT_FROM_EXT */
|
||||
|
||||
/****************************************************************************
|
||||
@ -501,6 +520,11 @@ int nxplayer_getmidisubformat(int fd)
|
||||
}
|
||||
#endif
|
||||
|
||||
int nxplayer_getmp3subformat(int fd)
|
||||
{
|
||||
return AUDIO_SUBFMT_PCM_MP3;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxplayer_fmtfromextension
|
||||
*
|
||||
@ -608,6 +632,8 @@ static int nxplayer_mediasearch(FAR struct nxplayer_s *pplayer,
|
||||
static int nxplayer_readbuffer(FAR struct nxplayer_s *pplayer,
|
||||
FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Validate the file is still open. It will be closed automatically when
|
||||
* we encounter the end of file (or, perhaps, a read error that we cannot
|
||||
* handle.
|
||||
@ -622,65 +648,17 @@ static int nxplayer_readbuffer(FAR struct nxplayer_s *pplayer,
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
/* Read data into the buffer. */
|
||||
|
||||
apb->nbytes = read(pplayer->fd, apb->samp, apb->nmaxbytes);
|
||||
apb->curbyte = 0;
|
||||
apb->flags = 0;
|
||||
|
||||
#ifdef CONFIG_NXPLAYER_HTTP_STREAMING_SUPPORT
|
||||
/* read data up to nmaxbytes from network */
|
||||
|
||||
while (0 < apb->nbytes && apb->nbytes < apb->nmaxbytes)
|
||||
ret = pplayer->ops->fill_data(pplayer->fd, apb);
|
||||
if (ret < 0)
|
||||
{
|
||||
int n = apb->nmaxbytes - apb->nbytes;
|
||||
int ret = read(pplayer->fd, &apb->samp[apb->nbytes], n);
|
||||
|
||||
if (0 >= ret)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
apb->nbytes += ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (apb->nbytes < apb->nmaxbytes)
|
||||
{
|
||||
#if defined (CONFIG_DEBUG_AUDIO_INFO) || defined (CONFIG_DEBUG_AUDIO_ERROR)
|
||||
int errcode = errno;
|
||||
|
||||
audinfo("Closing audio file, nbytes=%d errcode=%d\n",
|
||||
apb->nbytes, errcode);
|
||||
#endif
|
||||
|
||||
/* End of file or read error.. We are finished with this file in any
|
||||
* event.
|
||||
*/
|
||||
|
||||
close(pplayer->fd);
|
||||
pplayer->fd = -1;
|
||||
|
||||
/* Set a flag to indicate that this is the final buffer in the stream */
|
||||
|
||||
apb->flags |= AUDIO_APB_FINAL;
|
||||
|
||||
#ifdef CONFIG_DEBUG_AUDIO_ERROR
|
||||
/* Was this a file read error */
|
||||
|
||||
if (apb->nbytes == 0 && errcode != 0)
|
||||
{
|
||||
DEBUGASSERT(errcode > 0);
|
||||
auderr("ERROR: fread failed: %d\n", errcode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return OK to indicate that the buffer should be passed through to the
|
||||
* audio device. This does not necessarily indicate that data was read
|
||||
* correctly.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -1150,6 +1128,7 @@ err_out:
|
||||
pplayer->dev_fd = -1; /* Mark device as closed */
|
||||
mq_close(pplayer->mq); /* Close the message queue */
|
||||
mq_unlink(pplayer->mqname); /* Unlink the message queue */
|
||||
pplayer->ops = NULL; /* Clear offload parser */
|
||||
pplayer->state = NXPLAYER_STATE_IDLE; /* Go to IDLE */
|
||||
|
||||
sem_post(&pplayer->sem); /* Release the semaphore */
|
||||
@ -1780,6 +1759,7 @@ static int nxplayer_playinternal(FAR struct nxplayer_s *pplayer,
|
||||
#endif
|
||||
int tmpsubfmt = AUDIO_FMT_UNDEF;
|
||||
int ret;
|
||||
int c;
|
||||
|
||||
DEBUGASSERT(pplayer != NULL);
|
||||
DEBUGASSERT(pfilename != NULL);
|
||||
@ -1877,6 +1857,26 @@ static int nxplayer_playinternal(FAR struct nxplayer_s *pplayer,
|
||||
goto err_out_nodev;
|
||||
}
|
||||
|
||||
for (c = 0; c < sizeof(g_dec_ops) / sizeof(g_dec_ops[0]); c++)
|
||||
{
|
||||
if (g_dec_ops[c].format == filefmt)
|
||||
{
|
||||
pplayer->ops = &g_dec_ops[c];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pplayer->ops)
|
||||
{
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (pplayer->ops->pre_parse)
|
||||
{
|
||||
ret = pplayer->ops->pre_parse(pplayer->fd, &samprate,
|
||||
&nchannels, &bpsamp);
|
||||
}
|
||||
|
||||
/* Try to reserve the device */
|
||||
|
||||
#ifdef CONFIG_AUDIO_MULTI_SESSION
|
||||
@ -1906,6 +1906,7 @@ static int nxplayer_playinternal(FAR struct nxplayer_s *pplayer,
|
||||
cap_desc.caps.ac_controls.hw[0] = samprate;
|
||||
cap_desc.caps.ac_controls.b[3] = samprate >> 16;
|
||||
cap_desc.caps.ac_controls.b[2] = bpsamp;
|
||||
cap_desc.caps.ac_subtype = filefmt;
|
||||
|
||||
ioctl(pplayer->dev_fd, AUDIOIOC_CONFIGURE, (unsigned long)&cap_desc);
|
||||
}
|
||||
|
311
system/nxplayer/nxplayer_mp3.c
Normal file
311
system/nxplayer/nxplayer_mp3.c
Normal file
@ -0,0 +1,311 @@
|
||||
/****************************************************************************
|
||||
* apps/system/nxplayer/nxplayer_mp3.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <nuttx/audio/audio.h>
|
||||
|
||||
#include "system/nxplayer.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ID3V2_BIT_MASK 0x7F
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
const static uint16_t g_mpa_freq_tab[3] =
|
||||
{
|
||||
44100, 48000, 32000
|
||||
};
|
||||
|
||||
const static uint16_t g_mpa_bitrate_tab[2][3][15] =
|
||||
{
|
||||
{
|
||||
{
|
||||
0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
|
||||
},
|
||||
{
|
||||
0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
|
||||
},
|
||||
{
|
||||
0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256
|
||||
},
|
||||
{
|
||||
0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
|
||||
},
|
||||
{
|
||||
0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int nxplayer_check_mpeg(uint32_t header)
|
||||
{
|
||||
/* header */
|
||||
|
||||
if ((header & 0xffe00000) != 0xffe00000)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* version check */
|
||||
|
||||
if ((header & (3 << 19)) == 1 << 19)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* layer check */
|
||||
|
||||
if ((header & (3 << 17)) == 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* bit rate */
|
||||
|
||||
if ((header & (0xf << 12)) == 0xf << 12)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* frequency */
|
||||
|
||||
if ((header & (3 << 10)) == 3 << 10)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nxplayer_parse_mpeg(uint32_t header, FAR uint32_t *samplerate,
|
||||
FAR uint8_t *chans, FAR uint8_t *bps)
|
||||
{
|
||||
int sample_rate;
|
||||
int frame_size;
|
||||
int padding;
|
||||
int mpeg25;
|
||||
int sr_idx;
|
||||
int br_idx;
|
||||
int layer;
|
||||
int mode;
|
||||
int lsf;
|
||||
int ret;
|
||||
|
||||
ret = nxplayer_check_mpeg(header);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (header & (1 << 20))
|
||||
{
|
||||
lsf = (header & (1 << 19)) ? 0 : 1;
|
||||
mpeg25 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lsf = 1;
|
||||
mpeg25 = 1;
|
||||
}
|
||||
|
||||
layer = 4 - ((header >> 17) & 3);
|
||||
br_idx = (header >> 12) & 0xf;
|
||||
sr_idx = (header >> 10) & 3;
|
||||
padding = (header >> 9) & 1;
|
||||
mode = (header >> 6) & 3;
|
||||
|
||||
if (sr_idx >= sizeof(g_mpa_freq_tab) / sizeof(g_mpa_freq_tab[0]) ||
|
||||
br_idx >= 0xf)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sample_rate = g_mpa_freq_tab[sr_idx] >> (lsf + mpeg25);
|
||||
|
||||
if (br_idx != 0)
|
||||
{
|
||||
frame_size = g_mpa_bitrate_tab[lsf][layer - 1][br_idx];
|
||||
|
||||
switch (layer)
|
||||
{
|
||||
case 1:
|
||||
frame_size = (frame_size * 12000) / sample_rate;
|
||||
frame_size = (frame_size + padding) * 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
frame_size = (frame_size * 144000) / sample_rate;
|
||||
frame_size += padding;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 3:
|
||||
frame_size = (frame_size * 144000) / (sample_rate << lsf);
|
||||
frame_size += padding;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if no frame size computed, signal it */
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (samplerate)
|
||||
{
|
||||
*samplerate = sample_rate;
|
||||
}
|
||||
|
||||
if (chans)
|
||||
{
|
||||
*chans = mode == 3 ? 1 : 2;
|
||||
}
|
||||
|
||||
if (bps)
|
||||
{
|
||||
*bps = 16;
|
||||
}
|
||||
|
||||
return frame_size;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxplayer_parse_mp3
|
||||
*
|
||||
* nxplayer_parse_mp3() parse mp3 header, get samplerate, channels, bps.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxplayer_parse_mp3(int fd, FAR uint32_t *samplerate,
|
||||
FAR uint8_t *chans, FAR uint8_t *bps)
|
||||
{
|
||||
uint32_t mpa_header;
|
||||
uint8_t buffer[10];
|
||||
off_t position;
|
||||
int ret;
|
||||
|
||||
ret = read(fd, buffer, sizeof(buffer));
|
||||
if (ret < sizeof(buffer))
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
position = (buffer[6] & ID3V2_BIT_MASK) * 0x200000 +
|
||||
(buffer[7] & ID3V2_BIT_MASK) * 0x4000 +
|
||||
(buffer[8] & ID3V2_BIT_MASK) * 0x80 +
|
||||
(buffer[9] & ID3V2_BIT_MASK) +
|
||||
sizeof(buffer);
|
||||
|
||||
lseek(fd, position, SEEK_SET);
|
||||
|
||||
read(fd, buffer, 4);
|
||||
mpa_header = buffer[0] << 24 |
|
||||
buffer[1] << 16 |
|
||||
buffer[2] << 8 |
|
||||
buffer[3];
|
||||
|
||||
ret = nxplayer_parse_mpeg(mpa_header, samplerate, chans, bps);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
lseek(fd, position, SEEK_SET);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxplayer_fill_mp3
|
||||
*
|
||||
* nxplayer_fill_mp3 fill mp3 data into apb buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxplayer_fill_mp3(int fd, FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
uint32_t mpa_header;
|
||||
uint8_t header[16];
|
||||
int h_size = 4;
|
||||
int b_size;
|
||||
int size;
|
||||
int ret;
|
||||
|
||||
ret = read(fd, header, h_size);
|
||||
if (ret < h_size)
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
mpa_header = header[0] << 24 |
|
||||
header[1] << 16 |
|
||||
header[2] << 8 |
|
||||
header[3];
|
||||
|
||||
size = nxplayer_parse_mpeg(mpa_header, NULL, NULL, NULL);
|
||||
if (size < 0)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
memcpy(apb->samp, header, h_size);
|
||||
|
||||
b_size = size - h_size;
|
||||
ret = read(fd, apb->samp + h_size, b_size + 8);
|
||||
if (ret < b_size)
|
||||
{
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
lseek(fd, -8, SEEK_CUR);
|
||||
|
||||
apb->nbytes = size + 8;
|
||||
apb->curbyte = 0;
|
||||
apb->flags = 0;
|
||||
|
||||
return OK;
|
||||
}
|
104
system/nxplayer/nxplayer_pcm.c
Normal file
104
system/nxplayer/nxplayer_pcm.c
Normal file
@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
* apps/system/nxplayer/nxplayer_pcm.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/audio/audio.h>
|
||||
|
||||
#include "system/nxplayer.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nxplayer_fill_pcm
|
||||
*
|
||||
* nxplayer_fill_pcm fill pcm data into apb buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nxplayer_fill_pcm(int fd, FAR struct ap_buffer_s *apb)
|
||||
{
|
||||
/* Read data into the buffer. */
|
||||
|
||||
apb->nbytes = read(fd, apb->samp, apb->nmaxbytes);
|
||||
apb->curbyte = 0;
|
||||
apb->flags = 0;
|
||||
|
||||
#ifdef CONFIG_NXPLAYER_HTTP_STREAMING_SUPPORT
|
||||
/* read data up to nmaxbytes from network */
|
||||
|
||||
while (0 < apb->nbytes && apb->nbytes < apb->nmaxbytes)
|
||||
{
|
||||
int n = apb->nmaxbytes - apb->nbytes;
|
||||
int ret = read(fd, &apb->samp[apb->nbytes], n);
|
||||
|
||||
if (0 >= ret)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
apb->nbytes += ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (apb->nbytes < apb->nmaxbytes)
|
||||
{
|
||||
#if defined (CONFIG_DEBUG_AUDIO_INFO) || defined (CONFIG_DEBUG_AUDIO_ERROR)
|
||||
int errcode = errno;
|
||||
|
||||
audinfo("Closing audio file, nbytes=%d errcode=%d\n",
|
||||
apb->nbytes, errcode);
|
||||
#endif
|
||||
|
||||
/* Set a flag to indicate that this is the final buffer in the stream */
|
||||
|
||||
apb->flags |= AUDIO_APB_FINAL;
|
||||
|
||||
#ifdef CONFIG_DEBUG_AUDIO_ERROR
|
||||
/* Was this a file read error */
|
||||
|
||||
if (apb->nbytes == 0 && errcode != 0)
|
||||
{
|
||||
DEBUGASSERT(errcode > 0);
|
||||
auderr("ERROR: fread failed: %d\n", errcode);
|
||||
}
|
||||
#endif
|
||||
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
/* Return OK to indicate that the buffer should be passed through to the
|
||||
* audio device. This does not necessarily indicate that data was read
|
||||
* correctly.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
}
|
Loading…
Reference in New Issue
Block a user