static int nxplayer_playinternal()

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;
}