in system/nxplayer/nxplayer.c [1777:2044]
static int nxplayer_playinternal(FAR struct nxplayer_s *pplayer,
FAR const char *pfilename, int filefmt,
int subfmt, uint8_t nchannels,
uint8_t bpsamp, uint32_t samprate,
uint8_t chmap)
{
struct mq_attr attr;
struct sched_param sparam;
pthread_attr_t tattr;
struct audio_caps_desc_s cap_desc;
struct ap_buffer_info_s buf_info;
struct audio_caps_s caps;
int min_channels;
#ifdef CONFIG_NXPLAYER_INCLUDE_MEDIADIR
char path[PATH_MAX];
#endif
int tmpsubfmt = AUDIO_FMT_UNDEF;
int ret;
int c;
DEBUGASSERT(pplayer != NULL);
DEBUGASSERT(pfilename != NULL);
if (pplayer->state != NXPLAYER_STATE_IDLE)
{
return -EBUSY;
}
audinfo("==============================\n");
audinfo("Playing file %s\n", pfilename);
audinfo("==============================\n");
/* Test that the specified file exists */
#ifdef CONFIG_NXPLAYER_HTTP_STREAMING_SUPPORT
if ((pplayer->fd = _open_with_http(pfilename)) == -1)
#else
if ((pplayer->fd = open(pfilename, O_RDONLY)) == -1)
#endif
{
/* File not found. Test if its in the mediadir */
#ifdef CONFIG_NXPLAYER_INCLUDE_MEDIADIR
snprintf(path, sizeof(path), "%s/%s", pplayer->mediadir, pfilename);
if ((pplayer->fd = open(path, O_RDONLY)) == -1)
{
#ifdef CONFIG_NXPLAYER_MEDIA_SEARCH
/* File not found in the media dir. Do a search */
if (nxplayer_mediasearch(pplayer, pfilename, path,
sizeof(path)) != OK)
{
auderr("ERROR: Could not find file\n");
return -ENOENT;
}
#else
auderr("ERROR: Could not open %s or %s\n", pfilename, path);
return -ENOENT;
#endif /* CONFIG_NXPLAYER_MEDIA_SEARCH */
}
#else /* CONFIG_NXPLAYER_INCLUDE_MEDIADIR */
auderr("ERROR: Could not open %s\n", pfilename);
return -ENOENT;
#endif /* CONFIG_NXPLAYER_INCLUDE_MEDIADIR */
}
#ifdef CONFIG_NXPLAYER_FMT_FROM_EXT
/* Try to determine the format of audio file based on the extension */
if (filefmt == AUDIO_FMT_UNDEF)
{
filefmt = nxplayer_fmtfromextension(pplayer, pfilename, &tmpsubfmt);
}
#endif
#ifdef CONFIG_NXPLAYER_FMT_FROM_HEADER
/* If type not identified, then test for known header types */
if (filefmt == AUDIO_FMT_UNDEF)
{
filefmt = nxplayer_fmtfromheader(pplayer, &subfmt, &tmpsubfmt);
}
#endif
/* Test if we determined the file format */
if (filefmt == AUDIO_FMT_UNDEF)
{
/* Hmmm, it's some unknown / unsupported type */
auderr("ERROR: Unsupported format: %d\n", filefmt);
ret = -ENOSYS;
goto err_out_nodev;
}
/* Test if we have a sub format assignment from above */
if (subfmt == AUDIO_FMT_UNDEF)
{
subfmt = tmpsubfmt;
}
/* Try to open the device */
ret = nxplayer_opendevice(pplayer, filefmt, subfmt);
if (ret < 0)
{
/* Error opening the device */
auderr("ERROR: nxplayer_opendevice failed: %d\n", ret);
goto err_out_nodev;
}
for (c = 0; c < nitems(g_dec_ops); 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
ret = ioctl(pplayer->dev_fd, AUDIOIOC_RESERVE,
(unsigned long)&pplayer->session);
#else
ret = ioctl(pplayer->dev_fd, AUDIOIOC_RESERVE, 0);
#endif
if (ret < 0)
{
/* Device is busy or error */
auderr("ERROR: Failed to reserve device: %d\n", ret);
ret = -errno;
goto err_out;
}
caps.ac_len = sizeof(caps);
caps.ac_type = AUDIO_TYPE_OUTPUT;
caps.ac_subtype = AUDIO_TYPE_QUERY;
if (ioctl(pplayer->dev_fd, AUDIOIOC_GETCAPS,
(unsigned long)&caps) == caps.ac_len)
{
min_channels = caps.ac_channels >> 4;
if (min_channels != 0 && nchannels < min_channels)
{
ret = -EINVAL;
goto err_out;
}
}
if (nchannels && samprate && bpsamp)
{
#ifdef CONFIG_AUDIO_MULTI_SESSION
cap_desc.session = pplayer->session;
#endif
cap_desc.caps.ac_len = sizeof(struct audio_caps_s);
cap_desc.caps.ac_type = AUDIO_TYPE_OUTPUT;
cap_desc.caps.ac_channels = nchannels;
cap_desc.caps.ac_chmap = chmap;
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);
}
/* Query the audio device for its preferred buffer count */
if (ioctl(pplayer->dev_fd, AUDIOIOC_GETBUFFERINFO,
(unsigned long)&buf_info) != OK)
{
/* Driver doesn't report its buffer size. Use our default. */
buf_info.nbuffers = CONFIG_AUDIO_NUM_BUFFERS;
}
/* Create a message queue for the playthread */
attr.mq_maxmsg = buf_info.nbuffers + 8;
attr.mq_msgsize = sizeof(struct audio_msg_s);
attr.mq_curmsgs = 0;
attr.mq_flags = 0;
snprintf(pplayer->mqname, sizeof(pplayer->mqname), "/tmp/%0lx",
(unsigned long)((uintptr_t)pplayer));
pplayer->mq = mq_open(pplayer->mqname, O_RDWR | O_CREAT, 0644, &attr);
if (pplayer->mq == (mqd_t) -1)
{
/* Unable to open message queue! */
ret = -errno;
auderr("ERROR: mq_open failed: %d\n", ret);
goto err_out;
}
/* Register our message queue with the audio device */
ioctl(pplayer->dev_fd, AUDIOIOC_REGISTERMQ, (unsigned long)pplayer->mq);
/* Check if there was a previous thread and join it if there was
* to perform clean-up.
*/
nxplayer_jointhread(pplayer);
/* Start the playfile thread to stream the media file to the
* audio device.
*/
pthread_attr_init(&tattr);
sparam.sched_priority = sched_get_priority_max(SCHED_FIFO) - 9;
pthread_attr_setschedparam(&tattr, &sparam);
pthread_attr_setstacksize(&tattr,
CONFIG_NXPLAYER_PLAYTHREAD_STACKSIZE);
/* Add a reference count to the player for the thread and start the
* thread. We increment for the thread to avoid thread start-up
* race conditions.
*/
nxplayer_reference(pplayer);
ret = pthread_create(&pplayer->play_id, &tattr, nxplayer_playthread,
(pthread_addr_t) pplayer);
if (ret != OK)
{
auderr("ERROR: Failed to create playthread: %d\n", ret);
goto err_out;
}
/* Name the thread */
pthread_setname_np(pplayer->play_id, "playthread");
return OK;
err_out:
close(pplayer->dev_fd);
pplayer->dev_fd = -1;
err_out_nodev:
if (0 < pplayer->fd)
{
close(pplayer->fd);
pplayer->fd = -1;
}
return ret;
}