Beispiel #1
0
/**
 *
 *
 * @param pSession - pointer to pre-allocated hlsSession_t
 */
void hlsDownloaderThread(hlsSession_t* pSession)
{
    hlsStatus_t status = HLS_OK;

    if(pSession == NULL)
    {
        ERROR("pSession == NULL");
        pthread_exit(NULL);
    }

    TIMESTAMP(DBG_INFO, "Starting %s", __FUNCTION__);

    /* Is this normal playback or I-frame playback? */
    if((pSession->speed >= 0) && (pSession->speed <= 1))
    {
        status = hlsSegmentDownloadLoop(pSession);
    }
    else
    {
        status = hlsIFrameDownloadLoop(pSession);
    }

    pSession->downloaderStatus = status;

    if((status != HLS_OK) && (status != HLS_CANCELLED))
    {
        /* Send asynchronous error message to the player */
        srcPluginErr_t error;
        error.errCode = SRC_PLUGIN_ERR_SESSION_RESOURCE_FAILED;
        snprintf(error.errMsg, SRC_ERR_MSG_LEN, DEBUG_MSG("session %p download thread quit with status: %d", pSession, status));
        hlsPlayer_pluginErrCallback(pSession->pHandle, &error);

        ERROR("session %p download thread quit with status: %d", pSession, status);

        /* Put session in INVALID state */

        /* Block state changes */
        /*  pthread_mutex_lock(&(pSession->stateMutex)); */

        /* pSession->state = HLS_INVALID_STATE; */

        /* Leave critical section */
        /* pthread_mutex_unlock(&(pSession->stateMutex)); */
    }

    DEBUG(DBG_INFO,"session %p download thread exiting with status %d", pSession, status);
    pthread_exit(NULL);
}
Beispiel #2
0
	void Cells::add( const char* row, const char* columnFamily, const char* columnQualifier, uint64_t timestamp, const void* value, uint32_t valueLength, uint8_t flag ) {
		if( valueLength > Cell::MaxSize ) {
			HT4C_THROW_ARGUMENT("cell value exceeds the limit", "valueLength");
		}

		flag = FLAG( columnFamily, columnQualifier, flag );
		Cell cell( row
						 , CF(columnFamily)
						 , columnQualifier
						 , TIMESTAMP(timestamp, flag)
						 , value
						 , valueLength
						 , flag);

		cellsBuilder->add( cell.get(), true );
	}
Beispiel #3
0
 void CTRACE::TRACE_Init()
 {
  	// open the file for input:	
  if ( (fi = fopen(m_FileNameF, "a+") ) != NULL)
  {
   // printf ("file %s was open succesfully\n", FileNameF);
   m_FileIsOpen = 1;
  }
  else
  {
   printf ("file %s was not open\n", m_FileNameF);
   // getchar(); // nay3a, xyLe...
   m_FileIsOpen = 0;
  }	  
  // TRACEY("Start time: %d\n", Get1msTimeMS());
  TIMESTAMP(0);
  return;
 }
Beispiel #4
0
/**
 * End timing, store the elapsed time in t
 *
 * @pre   LpelTimingStart() was called on t
 */
void LpelTimingEnd(lpel_timing_t *t)
{
  lpel_timing_t start, end;

  /* get end time  */
  TIMESTAMP( &end);
  /* store start time */
  start = *t;

  /* calculate elapsed time to t,
   * assuming end > start and *.tv_nsec < TIMING_BILLION
   */
  if (end.tv_nsec < start.tv_nsec) {
    start.tv_nsec -= TIMING_BILLION;
    start.tv_sec  += 1L;
  }
  t->tv_nsec = end.tv_nsec - start.tv_nsec;
  t->tv_sec  = end.tv_sec  - start.tv_sec;
}
Beispiel #5
0
/**
 * Media group segment downloader thread
 *
 * @param pData - pointer to hlsGrpDwnldData_t
 */
void hlsGrpDownloaderThread(hlsGrpDwnldData_t* pData)
{
   hlsStatus_t status = HLS_OK;
   hlsSession_t *pSession = NULL;

   if(pData == NULL)
   {
      ERROR("pData == NULL");
      pthread_exit(NULL);
   }

   pSession = (hlsSession_t *)pData->pSession;
   if(pSession == NULL)
   {
      ERROR("pSession == NULL");
   }

   TIMESTAMP(DBG_INFO, "Starting %s for media group: %d",
         __FUNCTION__, pData->mediaGrpIdx);


   status = hlsGrpSegDwnldLoop(pSession, pData->mediaGrpIdx);

   pSession->groupDownloaderStatus[pData->mediaGrpIdx]= status;

   if((status != HLS_OK) && (status != HLS_CANCELLED))
   {
      /* Send asynchronous error message to the player */
      srcPluginErr_t error;
      error.errCode = SRC_PLUGIN_ERR_SESSION_RESOURCE_FAILED;
      snprintf(error.errMsg, SRC_ERR_MSG_LEN, DEBUG_MSG("session %p download thread quit with status: %d", pSession, status));
      hlsPlayer_pluginErrCallback(pSession->pHandle, &error);

      ERROR("session %p - Media group download thread quit with status: %d", pSession, status);
   }

   DEBUG(DBG_INFO,"session %p - Media group download thread exiting with status %d", pSession, status);
   pthread_exit(NULL);
}
Beispiel #6
0
/**
 * Media group segment downloader loop
 *
 * @param pSession - pointer to the HLS session
 * @param mediaGroupIdx - array index of the group in currentMediaGroup
 *
 * @return #hlsStatus_t
 */
hlsStatus_t hlsGrpSegDwnldLoop(hlsSession_t* pSession,
                               int mediaGroupIdx)
{
   hlsStatus_t status = HLS_OK;

   int pthread_status = 0;

   hlsPlaylist_t* pMediaPlaylist = NULL;

   hlsSegment_t* pSegment = NULL;
   hlsSegment_t* pSegmentCopy = NULL;

   int proposedBitrateIndex = 0;
   struct timespec wakeTime;
   llStatus_t llerror = LL_OK;
   playbackControllerSignal_t* pSignal = NULL;
   struct timespec oldLastBitrateChange;
   srcPlayerMode_t playerMode;

   TIMESTAMP(DBG_INFO, "Starting %s - Media group: %s",
         __FUNCTION__, pSession->pCurrentGroup[mediaGroupIdx]->groupID);

   if(pSession == NULL)
   {
      ERROR("invalid parameter: psession");
      return HLS_INVALID_PARAMETER;
   }
   if(mediaGroupIdx >= pSession->currentGroupCount)
   {
      ERROR("invalid parameter: mediaGroupIdx");
      return HLS_INVALID_PARAMETER;
   }

   do
   {
      pMediaPlaylist = pSession->pCurrentGroup[mediaGroupIdx]->pPlaylist;

      /* Allocate a segment to keep a local copy of segment information */
      pSegmentCopy = newHlsSegment();
      if(pSegmentCopy == NULL)
      {
         ERROR("newHlsSegment() failed");
         status = HLS_MEMORY_ERROR;
         break;
      }

      while(status == HLS_OK)
      {
         /* If the downloader was signalled to exit, return HLS_CANCELLED */
         if(pSession->bKillDownloader)
         {
            DEBUG(DBG_WARN, "downloader signalled to stop");
            status = HLS_CANCELLED;
            break;
         }

         /* Get current time */
         if(clock_gettime(CLOCK_MONOTONIC, &wakeTime) != 0)
         {
            ERROR("failed to get current time");
            status = HLS_ERROR;
            break;
         }

         /* Get playlist READ lock */
         pthread_rwlock_rdlock(&(pSession->playlistRWLock));

         /* Get the next segment */
         status = getNextSegment(pMediaPlaylist, &pSegment);
         if(status != HLS_OK)
         {
            ERROR("failed to find next segment");
            /* Release playlist lock */
            pthread_rwlock_unlock(&(pSession->playlistRWLock));
            break;
         }

         /* Did we get a valid segment? */
         if(pSegment != NULL)
         {
            /* Make a local copy of the segment */
            status = copyHlsSegment(pSegment, pSegmentCopy);
            if(status != HLS_OK)
            {
               ERROR("failed to make local segment copy");
               /* Release playlist lock */
               pthread_rwlock_unlock(&(pSession->playlistRWLock));
               break;
            }

            /* Prepend the playlist's baseURL, if necessary */
            status = createFullURL(&(pSegmentCopy->URL), pMediaPlaylist->baseURL);
            if(status != HLS_OK)
            {
               ERROR("error creating full URL");
               /* Release playlist lock */
               pthread_rwlock_unlock(&(pSession->playlistRWLock));
               break;
            }

            /* We no longer need a reference to the parsed segment */
            pSegment = NULL;

            /* Release playlist lock */
            pthread_rwlock_unlock(&(pSession->playlistRWLock));

            /* Determine the player mode based on speed */
            if(pSession->speed == 0.0)
            {
               playerMode = SRC_PLAYER_MODE_PAUSE;
            }
            else
            {
               playerMode = SRC_PLAYER_MODE_NORMAL;
            }

            status = hlsDwnldThreadsSync(pSession, mediaGroupIdx, pMediaPlaylist, pSegmentCopy);
            if(HLS_OK != status)
            {
               break;
            }

            status = downloadAndPushSegment(pSession, pSegmentCopy, wakeTime, playerMode,
                                            SRC_STREAM_NUM_MAIN + mediaGroupIdx + 1);
            if(status != HLS_OK)
            {
               if(status == HLS_CANCELLED)
               {
                  DEBUG(DBG_WARN, "downloader signalled to stop");
                  break;
               }
               else
               {
                  ERROR("Failed to download segment");
                  break;
               }
            }
         }
         else
         {
            /* If we aren't playing then we never even got the first segment, so quit */
            if(pSession->state != HLS_PLAYING)
            {
               ERROR("failed to get first segment");
               status = HLS_ERROR;
               /* Release playlist lock */
               pthread_rwlock_unlock(&(pSession->playlistRWLock));
               break;
            }

            if(!pMediaPlaylist->pMediaData->bHaveCompletePlaylist) /* Live stream */
            {
               /* Release playlist lock */
               pthread_rwlock_unlock(&(pSession->playlistRWLock));

               /* If we didn't get a segment we've hit EOS */
               DEBUG(DBG_NOISE,"EOS -- no more segments in live playlist");

               /* If we have hit EOS on a live stream, then we just need
                  to wait for the playlist to update with new segments */

               /* Lock the downloader wake mutex */
               if(pthread_mutex_lock(&(pSession->downloaderWakeMutex)) != 0)
               {
                  ERROR("failed to lock downloader wake mutex");
                  status = HLS_ERROR;
                  break;
               }

               /* Wait for LOOP_SECS before going again */
               wakeTime.tv_sec += DOWNLOADER_LOOP_SECS;

               DEBUG(DBG_NOISE,"sleeping %d seconds until %d", (int)DOWNLOADER_LOOP_SECS, (int)wakeTime.tv_sec);

               /* Wait until wakeTime */
               pthread_status = PTHREAD_COND_TIMEDWAIT(&(pSession->downloaderWakeCond), &(pSession->downloaderWakeMutex), &wakeTime);

               /* Unlock the downloader wake mutex */
               if(pthread_mutex_unlock(&(pSession->downloaderWakeMutex)) != 0)
               {
                  ERROR("failed to unlock downloader wake mutex");
                  status = HLS_ERROR;
                  break;
               }

               /* If the timedwait call failed we need to bail */
               if((pthread_status != ETIMEDOUT) && (pthread_status != 0))
               {
                  ERROR("failed to timedwait on the downloader wake condition");
                  status = HLS_ERROR;
                  break;
               }
            }
            else /* VOD stream */
            {
               /* Release playlist lock */
               pthread_rwlock_unlock(&(pSession->playlistRWLock));

               DEBUG(DBG_INFO,"EOF(VOD) - Media Group %s download loop", pSession->pCurrentGroup[mediaGroupIdx]->groupID);

               /* Allocate a new playback controller signal */
               pSignal = malloc(sizeof(playbackControllerSignal_t));
               if(pSignal == NULL)
               {
                   ERROR("malloc error");
                   status = HLS_MEMORY_ERROR;
                   break;
               }

               *pSignal = PBC_DOWNLOAD_COMPLETE;

               /* Push the message to the playback controller message queue */
               llerror = pushMsg(pSession->playbackControllerMsgQueue, (void*)pSignal);
               if(llerror != LL_OK)
               {
                  ERROR("failed to signal the playback controller");
                  free(pSignal);
                  status = HLS_ERROR;
                  break;
               }

               /* Release reference to signal -- playback controller will free */
               pSignal = NULL;

               break;
            }
         }

         /* Make sure we're still in a valid state */
         if(pSession->state == HLS_INVALID_STATE)
         {
            status = HLS_STATE_ERROR;
            break;
         }
      }
      if(status != HLS_OK)
      {
         break;
      }

   } while (0);

   /* Clean up */
   freeSegment(pSegmentCopy);

   return status;
}
Beispiel #7
0
hlsStatus_t hlsIFrameDownloadLoop(hlsSession_t* pSession)
{
    hlsStatus_t status = HLS_OK;

    hlsPlaylist_t* pMediaPlaylist = NULL;
    hlsSegment_t* pSegment = NULL;

    hlsSegment_t* pSegmentCopy = NULL;

    double trickDuration = 0;

    double segmentPositionFromEnd = 0;

    //int proposedBitrateIndex = 0;

    struct timespec wakeTime;

    playbackControllerSignal_t* pSignal = NULL;

    llStatus_t llerror = LL_OK;

    if(pSession == NULL)
    {
        ERROR("invalid parameter");
        return HLS_INVALID_PARAMETER;
    }

    TIMESTAMP(DBG_INFO, "Starting %s", __FUNCTION__);

    do
    {
        /* Allocate a segment to keep a local copy of segment information */
        pSegmentCopy = newHlsSegment();
        if(pSegmentCopy == NULL)
        {
            ERROR("newHlsSegment() failed");
            status = HLS_MEMORY_ERROR;
            break;
        }

        /* Get current time as initial wakeTime */
        if(clock_gettime(CLOCK_MONOTONIC, &wakeTime) != 0)
        {
            ERROR("failed to get current time");
            status = HLS_ERROR;
            break;
        }

        while(status == HLS_OK)
        {
            /* If the downloader was signalled to exit, return HLS_CANCELLED */
            if(pSession->bKillDownloader)
            {
                DEBUG(DBG_WARN, "downloader signalled to stop");
                status = HLS_CANCELLED;
                break;
            }

            /* Get playlist READ lock */
            pthread_rwlock_rdlock(&(pSession->playlistRWLock));

            /* Get the current playlist */
            pMediaPlaylist = pSession->pCurrentPlaylist;
            if((pMediaPlaylist == NULL) ||
               (pMediaPlaylist->type != PL_MEDIA) ||
               (pMediaPlaylist->pMediaData == NULL))
            {
                ERROR("invalid playlist for playback");
                status = HLS_ERROR;
                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));
                break;
            }

            /* Get the next I-frame */
            status = getNextIFrame(pMediaPlaylist, &pSegment, pSession->speed);
            if(status != HLS_OK)
            {
                ERROR("failed to find next I-Frame");
                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));
                break;
            }

            /* Did we get a valid segment? */
            if(pSegment != NULL)
            {
                /* Make a local copy of the segment */
                status = copyHlsSegment(pSegment, pSegmentCopy);
                if(status != HLS_OK)
                {
                    ERROR("failed to make local segment copy");
                    /* Release playlist lock */
                    pthread_rwlock_unlock(&(pSession->playlistRWLock));
                    break;
                }

                /* Prepend the playlist's baseURL, if necessary */
                status = createFullURL(&(pSegmentCopy->URL), pMediaPlaylist->baseURL);
                if(status != HLS_OK)
                {
                    ERROR("error creating full URL");
                    /* Release playlist lock */
                    pthread_rwlock_unlock(&(pSession->playlistRWLock));
                    break;
                }

                DEBUG(DBG_NOISE,"Segment download URL: %s", pSegmentCopy->URL);

                /* If we are rewinding, the segmentDuration (i.e. the duration between
                   the current I-frame and the previous I-frame) is actually the duration
                   of the previous I-frame */
                if(pSession->speed < 0)
                {
                    if(pSegment->pParentNode == NULL)
                    {
                        ERROR("NULL parent node");
                        status = HLS_ERROR;
                        /* Release playlist lock */
                        pthread_rwlock_unlock(&(pSession->playlistRWLock));
                        break;
                    }

                    /* If we have the first I-frame in the playlist, then use the current I-frame duration
                       (since there is no previous I-frame). */
                    if(pSegment->pParentNode->pPrev == NULL)
                    {
                        pSegmentCopy->duration = pSegment->duration;
                    }
                    else
                    {
                        if(pSegment->pParentNode->pPrev->pData == NULL)
                        {
                            ERROR("empty segment node");
                            status = HLS_ERROR;
                            /* Release playlist lock */
                            pthread_rwlock_unlock(&(pSession->playlistRWLock));
                            break;
                        }

                        pSegmentCopy->duration = ((hlsSegment_t*)(pSegment->pParentNode->pPrev->pData))->duration;
                    }
                }

                /* Save this segment's positionFromEnd */
                status = getPositionFromEnd(pMediaPlaylist, pSegment, &segmentPositionFromEnd);
                if(status != HLS_OK)
                {
                    ERROR("problem getting segment position");
                    break;
                }

                /* We no longer need a reference to the parsed segment */
                pSegment = NULL;

                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));

                status = downloadAndPushSegment(pSession, pSegmentCopy, wakeTime, SRC_PLAYER_MODE_LOW_DELAY,
                                                SRC_STREAM_NUM_MAIN);
                if(status != HLS_OK)
                {
                    if(status == HLS_CANCELLED)
                    {
                        DEBUG(DBG_WARN, "downloader signalled to stop");
                        break;
                    }
                    else
                    {
                        ERROR("Failed to download segment");
                        break;
                    }
                }

                /* Calculate the display time for the new frame (i.e. how long
                   to wait before displaying the next frame) */

                /* Get current time */
                if(clock_gettime(CLOCK_MONOTONIC, &wakeTime) != 0)
                {
                    ERROR("failed to get current time");
                    status = HLS_ERROR;
                    break;
                }

                DEBUG(DBG_INFO,"current time: %f", ((wakeTime.tv_sec)*1.0) + (wakeTime.tv_nsec/1000000000.0));

                /* Get the display time for the new frame */
                trickDuration = iFrameTrickDuration(pSegmentCopy->duration, pSession->speed);

                /* Set wakeTime to current time + trickDuration */
                wakeTime.tv_sec += floorf(trickDuration);
                wakeTime.tv_nsec += (trickDuration - floorf(trickDuration)) * 1000000000;

                /* Handle a rollover of the nanosecond portion of wakeTime */
                while(wakeTime.tv_nsec >= 1000000000)
                {
                    wakeTime.tv_sec += 1;
                    wakeTime.tv_nsec -= 1000000000;
                }

                /* Get playlist WRITE lock */
                pthread_rwlock_wrlock(&(pSession->playlistRWLock));

                /* Since the I-frames are displayed as soon as we send them to the player, update our
                   current positionFromEnd here, instead of relying on PTS callbacks */
                pMediaPlaylist->pMediaData->positionFromEnd = segmentPositionFromEnd;

                // TODO: noise...
                DEBUG(DBG_INFO, "new position from end: %f seconds", segmentPositionFromEnd);

                // TODO: Ignore bitrate switching for I-frames for now...
#if 0
                // Check if we want to switch bitrate, if we have > 1 variant
                if(pSession->pPlaylist->type == PL_VARIANT)
                {
                    if((pSession->pCurrentProgram != NULL) &&
                       (pSession->pCurrentProgram->pAvailableBitrates != NULL) &&
                       (pSession->pCurrentProgram->pStreams != NULL))
                    {
                        proposedBitrateIndex = abrClientGetNewBitrate(pSession->lastSegmentDldRate, pSession->avgSegmentDldRate, pSession->timeBuffered,
                                                                      pSession->pCurrentProgram->pStreams->numElements, pSession->pCurrentProgram->pAvailableBitrates,
                                                                      pMediaPlaylist->pMediaData->bitrate, pSession->minBitrate, pSession->maxBitrate,
                                                                      &(pSession->lastBitrateChange), &(pSession->playbackStart));
                        if((proposedBitrateIndex < 0) || (proposedBitrateIndex >= pSession->pCurrentProgram->pStreams->numElements))
                        {
                            // TODO: ??? Anything else?
                            ERROR("Problem with bitrate window (rateMin/rateMax) prevented bitrate switching!");
                        }
                        else
                        {
                            status = changeBitrate(pSession, pSession->pCurrentProgram->pAvailableBitrates[proposedBitrateIndex]);
                            if(status != HLS_OK)
                            {
                                ERROR("failed to change bitrate");
                                /* Release playlist lock */
                                pthread_rwlock_unlock(&(pSession->playlistRWLock));
                                break;
                            }
                        }
                    }
                    else
                    {
                        ERROR("current program malformed or invalid");
                        status = HLS_ERROR;
                        /* Release playlist lock */
                        pthread_rwlock_unlock(&(pSession->playlistRWLock));
                        break;
                    }
                }
                else
                {
                    DEBUG(DBG_INFO, "Skipped bitrate-switching logic (playlist type is not PL_VARIANT)");
                }
#endif

                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));
            }
            else
            {
                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));

                /* If we aren't playing then we never even got the first I-frame, so quit */
                if(pSession->state != HLS_PLAYING)
                {
                    ERROR("failed to get first I-frame");
                    status = HLS_ERROR;
                    break;
                }

                if(1 != pSession->bKillDownloader)
                {
                   /* If we didn't get an I-frame, signal the playback controller
                      thread that the download is complete and the downloader is exiting. */

                   /* Allocate a new playback controller signal */
                   pSignal = malloc(sizeof(playbackControllerSignal_t));
                   if(pSignal == NULL)
                   {
                      ERROR("malloc error");
                      status = HLS_MEMORY_ERROR;
                      break;
                   }

                   *pSignal = PBC_DOWNLOAD_COMPLETE;

                   /* Push the message to the playback controller message queue */
                   llerror = pushMsg(pSession->playbackControllerMsgQueue, (void*)pSignal);
                   if(llerror != LL_OK)
                   {
                      ERROR("failed to signal the playback controller");
                      free(pSignal);
                      status = HLS_ERROR;
                      break;
                   }

                   /* Release reference to signal -- playback controller will free */
                   pSignal = NULL;

                   /* Stop the downloader thread */
                   pSession->bKillDownloader = 1;
                }
            }

            /* Make sure we're still in a valid state */
            if(pSession->state == HLS_INVALID_STATE)
            {
                status = HLS_STATE_ERROR;
                break;
            }
        }
        if(status != HLS_OK)
        {
            break;
        }

    } while (0);

    /* Clean up */
    freeSegment(pSegmentCopy);

    return status;
}
Beispiel #8
0
hlsStatus_t hlsSegmentDownloadLoop(hlsSession_t* pSession)
{
    hlsStatus_t status = HLS_OK;

    int pthread_status = 0;

    hlsPlaylist_t* pMediaPlaylist = NULL;
    hlsSegment_t* pSegment = NULL;

    hlsSegment_t* pSegmentCopy = NULL;

    int proposedBitrateIndex = 0;
    struct timespec wakeTime;
    llStatus_t llerror = LL_OK;
    playbackControllerSignal_t* pSignal = NULL;
    struct timespec oldLastBitrateChange;
    srcPlayerMode_t playerMode;



    if(pSession == NULL)
    {
        ERROR("invalid parameter");
        return HLS_INVALID_PARAMETER;
    }

    TIMESTAMP(DBG_INFO, "Starting %s", __FUNCTION__);

    do
    {
        /* Allocate a segment to keep a local copy of segment information */
        pSegmentCopy = newHlsSegment();
        if(pSegmentCopy == NULL)
        {
            ERROR("newHlsSegment() failed");
            status = HLS_MEMORY_ERROR;
            break;
        }

        while(status == HLS_OK)
        {
            /* If the downloader was signalled to exit, return HLS_CANCELLED */
            if(pSession->bKillDownloader)
            {
                DEBUG(DBG_WARN, "downloader signalled to stop");
                status = HLS_CANCELLED;
                break;
            }

            /* Get current time */
            if(clock_gettime(CLOCK_MONOTONIC, &wakeTime) != 0)
            {
                ERROR("failed to get current time");
                status = HLS_ERROR;
                break;
            }

            /* Get playlist READ lock */
            pthread_rwlock_rdlock(&(pSession->playlistRWLock));

            /* Get the current playlist */
            pMediaPlaylist = pSession->pCurrentPlaylist;
            if((pMediaPlaylist == NULL) ||
               (pMediaPlaylist->type != PL_MEDIA) ||
               (pMediaPlaylist->pMediaData == NULL))
            {
                ERROR("invalid playlist for playback");
                status = HLS_ERROR;
                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));
                break;
            }

            /* Get the next segment */
            // GET NEXT SEGMENT SHOULD LOAD UP THE DECRYPTION INFOMATION RMS
            status = getNextSegment(pMediaPlaylist, &pSegment);
            if(status != HLS_OK)
            {
                ERROR("failed to find next segment");
                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));
                break;
            }

            /* Did we get a valid segment? */
            if(pSegment != NULL)
            {
                /* Make a local copy of the segment */
                status = copyHlsSegment(pSegment, pSegmentCopy);
                if(status != HLS_OK)
                {
                    ERROR("failed to make local segment copy");
                    /* Release playlist lock */
                    pthread_rwlock_unlock(&(pSession->playlistRWLock));
                    break;
                }

                /* Prepend the playlist's baseURL, if necessary */
                status = createFullURL(&(pSegmentCopy->URL), pMediaPlaylist->baseURL);
                if(status != HLS_OK)
                {
                    ERROR("error creating full URL");
                    /* Release playlist lock */
                    pthread_rwlock_unlock(&(pSession->playlistRWLock));
                    break;
                }
                // here is the segment, if it's encrypted we need to attach
                // some decryption infomation here.

                //
                // RMS RETARDED!!!! Key information was in the original pSegment structure
                // but instead of sending that the original author sends a copy.  WTF???
                //

                /* We no longer need a reference to the parsed segment */
                pSegment = NULL;

                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));

                /* Determine the player mode based on speed */
                if(pSession->speed == 0.0)
                {
                   playerMode = SRC_PLAYER_MODE_PAUSE;
                }
                else
                {
                   playerMode = SRC_PLAYER_MODE_NORMAL;
                }
                status = downloadAndPushSegment(pSession, pSegmentCopy, wakeTime, playerMode,
                                                SRC_STREAM_NUM_MAIN);
                if(status != HLS_OK)
                {
                    if(status == HLS_CANCELLED)
                    {
                        DEBUG(DBG_WARN, "downloader signalled to stop");
                        break;
                    }
                    else
                    {
                        ERROR("Failed to download segment");
                        break;
                    }
                }

                /* timeBuffered is also updated whenever we process a PTS
                   in the playerEvtCallback -- block those callbacks while
                   we update it here */
                pthread_mutex_lock(&(pSession->playerEvtMutex));

                /* Increment our buffer count */
                pSession->timeBuffered += pSegmentCopy->duration;

                /* Unblock the playerEvtCallback */
                pthread_mutex_unlock(&(pSession->playerEvtMutex));

                /* Get playlist WRITE lock */
                pthread_rwlock_wrlock(&(pSession->playlistRWLock));

                // Check if we want to switch bitrate, if we have > 1 variant
                if(pSession->pPlaylist->type == PL_VARIANT)
                {
                    if((pSession->pCurrentProgram != NULL) &&
                       (pSession->pCurrentProgram->pAvailableBitrates != NULL) &&
                       (pSession->pCurrentProgram->pStreams != NULL))
                    {
                        /* Save off pSession->lastBitrateChange in case we fail to shift and need to revert to old values */
                        oldLastBitrateChange.tv_sec = pSession->lastBitrateChange.tv_sec;
                        oldLastBitrateChange.tv_nsec = pSession->lastBitrateChange.tv_nsec;

                        proposedBitrateIndex = abrClientGetNewBitrate(pSession->lastSegmentDldRate, pSession->avgSegmentDldRate, (float)(pSession->timeBuffered),
                                                                      pSession->pCurrentProgram->pStreams->numElements, pSession->pCurrentProgram->pAvailableBitrates,
                                                                      pMediaPlaylist->pMediaData->bitrate, pSession->minBitrate, pSession->maxBitrate,
                                                                      &(pSession->lastBitrateChange), &(pSession->playbackStart));
                        if((proposedBitrateIndex < 0) || (proposedBitrateIndex >= pSession->pCurrentProgram->pStreams->numElements))
                        {
                            // TODO: ??? Anything else?
                            ERROR("Problem with bitrate window (rateMin/rateMax) prevented bitrate switching!");
                        }
                        else
                        {
                            status = changeBitrate(pSession, pSession->pCurrentProgram->pAvailableBitrates[proposedBitrateIndex]);
                            if(status != HLS_OK)
                            {
                                if(status == HLS_DL_ERROR)
                                {
                                    /* If we failed to switch because of a network error, keep going for now and
                                       try switching again on the next go-around. */
                                    DEBUG(DBG_WARN, "problem downloading new playlist for bitrate switch attempt -- will retry");

                                    /* Since we didn't shift bitrates, revert lastBitrateChange to old value (which was overwritten by abrClientGetNewBitrate() */

                                    // TODO: have the plugin update lastBitrateChange instead of the adaptec code?
                                    pSession->lastBitrateChange.tv_sec = oldLastBitrateChange.tv_sec;
                                    pSession->lastBitrateChange.tv_nsec = oldLastBitrateChange.tv_nsec;

                                    status = HLS_OK;
                                }
                                else
                                {
                                    ERROR("failed to change bitrate");
                                    /* Release playlist lock */
                                    pthread_rwlock_unlock(&(pSession->playlistRWLock));
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        ERROR("current program malformed or invalid");
                        status = HLS_ERROR;
                        /* Release playlist lock */
                        pthread_rwlock_unlock(&(pSession->playlistRWLock));
                        break;
                    }
                }
                else
                {
                    DEBUG(DBG_INFO, "Skipped bitrate-switching logic (playlist type is not PL_VARIANT)");
                }

                /* Release playlist lock */
                pthread_rwlock_unlock(&(pSession->playlistRWLock));
            }
            else
            {
                /* If we aren't playing then we never even got the first segment, so quit */
                if(pSession->state != HLS_PLAYING)
                {
                    ERROR("failed to get first segment");
                    status = HLS_ERROR;
                    /* Release playlist lock */
                    pthread_rwlock_unlock(&(pSession->playlistRWLock));
                    break;
                }

                /* Did this happen on a live or a VoD stream? */
                if(pSession->pCurrentPlaylist->pMediaData->bHaveCompletePlaylist) /* VoD stream */
                {
                    /* Release playlist lock */
                    pthread_rwlock_unlock(&(pSession->playlistRWLock));

                    /* If we didn't get a segment we've hit EOF */
                    DEBUG(DBG_NOISE,"EOF -- no more segments in VoD playlist");

                    if(1 != pSession->bKillDownloader)
                    {
                       /* If we've hit EOF on a VoD stream, then the downloader needs to signal the
                          playback controller and exit. The playback controller will monitor the
                          buffer level and signal EOF to the player once timeBuffered reaches 0. */

                       /* Allocate a new playback controller signal */
                       pSignal = malloc(sizeof(playbackControllerSignal_t));
                       if(pSignal == NULL)
                       {
                          ERROR("malloc error");
                          status = HLS_MEMORY_ERROR;
                          break;
                       }

                       *pSignal = PBC_DOWNLOAD_COMPLETE;

                       /* Push the message to the playback controller message queue */
                       llerror = pushMsg(pSession->playbackControllerMsgQueue, (void*)pSignal);
                       if(llerror != LL_OK)
                       {
                          ERROR("failed to signal the playback controller");
                          free(pSignal);
                          status = HLS_ERROR;
                          break;
                       }

                       /* Release reference to signal -- playback controller will free */
                       pSignal = NULL;

                       /* Stop the downloader thread */
                       pSession->bKillDownloader = 1;
                    }
                }
                else /* LIVE stream */
                {
                    /* Release playlist lock */
                    pthread_rwlock_unlock(&(pSession->playlistRWLock));

                    /* If we didn't get a segment we've hit EOS */
                    DEBUG(DBG_NOISE,"EOS -- no more segments in live playlist");

                    /* If we have hit EOS on a live stream, then we just need
                       to wait for the playlist to update with new segments */

                    /* Lock the downloader wake mutex */
                    if(pthread_mutex_lock(&(pSession->downloaderWakeMutex)) != 0)
                    {
                        ERROR("failed to lock downloader wake mutex");
                        status = HLS_ERROR;
                        break;
                    }

                    /* Wait for LOOP_SECS before going again */
                    wakeTime.tv_sec += DOWNLOADER_LOOP_SECS;

                    DEBUG(DBG_NOISE,"sleeping %d seconds until %d", (int)DOWNLOADER_LOOP_SECS, (int)wakeTime.tv_sec);

                    /* Wait until wakeTime */
                    pthread_status = PTHREAD_COND_TIMEDWAIT(&(pSession->downloaderWakeCond), &(pSession->downloaderWakeMutex), &wakeTime);

                    /* Unlock the downloader wake mutex */
                    if(pthread_mutex_unlock(&(pSession->downloaderWakeMutex)) != 0)
                    {
                        ERROR("failed to unlock downloader wake mutex");
                        status = HLS_ERROR;
                        break;
                    }

                    /* If the timedwait call failed we need to bail */
                    if((pthread_status != ETIMEDOUT) && (pthread_status != 0))
                    {
                        ERROR("failed to timedwait on the downloader wake condition");
                        status = HLS_ERROR;
                        break;
                    }
                }
            }

            /* Make sure we're still in a valid state */
            if(pSession->state == HLS_INVALID_STATE)
            {
                status = HLS_STATE_ERROR;
                break;
            }
        }
        if(status != HLS_OK)
        {
            break;
        }

    } while (0);

    /* Clean up */
    freeSegment(pSegmentCopy);

    return status;
}
TIMESTAMP now()
{
    return TIMESTAMP(SDL_GetTicks());
}
Beispiel #10
0
double
VTIM_parse(const char *p)
{
	double t;
	int month = 0, year = 0, weekday = -1, mday = 0;
	int hour = 0, min = 0, sec = 0;
	int d, leap;

	while (*p == ' ')
		p++;

	if (*p >= '0' && *p <= '9') {
		/* ISO8601 -- "1994-11-06T08:49:37" */
		DIGIT(1000, year);
		DIGIT(100, year);
		DIGIT(10, year);
		DIGIT(1, year);
		MUSTBE('-');
		DIGIT(10, month);
		DIGIT(1, month);
		MUSTBE('-');
		DIGIT(10, mday);
		DIGIT(1, mday);
		MUSTBE('T');
		TIMESTAMP();
	} else {
		WEEKDAY();
		assert(weekday >= 0 && weekday <= 6);
		if (*p == ',') {
			/* RFC822 & RFC1123 - "Sun, 06 Nov 1994 08:49:37 GMT" */
			p++;
			MUSTBE(' ');
			DIGIT(10, mday);
			DIGIT(1, mday);
			MUSTBE(' ');
			MONTH();
			MUSTBE(' ');
			DIGIT(1000, year);
			DIGIT(100, year);
			DIGIT(10, year);
			DIGIT(1, year);
			MUSTBE(' ');
			TIMESTAMP();
			MUSTBE(' ');
			MUSTBE('G');
			MUSTBE('M');
			MUSTBE('T');
		} else if (*p == ' ') {
			/* ANSI-C asctime() -- "Sun Nov  6 08:49:37 1994" */
			p++;
			MONTH();
			MUSTBE(' ');
			if (*p != ' ')
				DIGIT(10, mday);
			else
				p++;
			DIGIT(1, mday);
			MUSTBE(' ');
			TIMESTAMP();
			MUSTBE(' ');
			DIGIT(1000, year);
			DIGIT(100, year);
			DIGIT(10, year);
			DIGIT(1, year);
		} else if (!memcmp(p, more_weekday[weekday],
		    strlen(more_weekday[weekday]))) {
			/* RFC850 -- "Sunday, 06-Nov-94 08:49:37 GMT" */
			p += strlen(more_weekday[weekday]);
			MUSTBE(',');
			MUSTBE(' ');
			DIGIT(10, mday);
			DIGIT(1, mday);
			MUSTBE('-');
			MONTH();
			MUSTBE('-');
			DIGIT(10, year);
			DIGIT(1, year);
			year += 1900;
			if (year < 1969)
				year += 100;
			MUSTBE(' ');
			TIMESTAMP();
			MUSTBE(' ');
			MUSTBE('G');
			MUSTBE('M');
			MUSTBE('T');
		} else
			FAIL();
	}

	while (*p == ' ')
		p++;

	if (*p != '\0')
		FAIL();

	if (sec < 0 || sec > 60)	/* Leapseconds! */
		FAIL();
	if (min < 0 || min > 59)
		FAIL();
	if (hour < 0 || hour > 23)
		FAIL();
	if (month < 1 || month > 12)
		FAIL();
	if (mday < 1 || mday > days_in_month[month - 1])
		FAIL();
	if (year < 1899)
		FAIL();

	leap =
	    ((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0);

	if (month == 2 && mday > 28 && !leap)
		FAIL();

	if (sec == 60)			/* Ignore Leapseconds */
		sec--;

	t = ((hour * 60.) + min) * 60. + sec;

	d = (mday - 1) + days_before_month[month - 1];

	if (month > 2 && leap)
		d++;

	d += (year % 100) * 365;	/* There are 365 days in a year */

	if ((year % 100) > 0)		/* And a leap day every four years */
		d += (((year % 100) - 1) / 4);

	d += ((year / 100) - 20) *	/* Days relative to y2000 */
	    (100 * 365 + 24);		/* 24 leapdays per year in a century */

	d += ((year - 1) / 400) - 4;	/* And one more every 400 years */

	/*
	 * Now check weekday, if we have one.
	 * 6 is because 2000-01-01 was a saturday.
	 * 10000 is to make sure the modulus argument is always positive
	 */
	if (weekday != -1 && (d + 6 + 7 * 10000) % 7 != weekday)
		FAIL();

	t += d * 86400.;

	t += 10957. * 86400.;		/* 10957 days frm UNIX epoch to y2000 */

	return (t);
}
static void *run(void * _args)
{
    // Cast _args
    struct guppi_thread_args *args = (struct guppi_thread_args *)_args;

    THREAD_RUN_BEGIN(args);

    THREAD_RUN_SET_AFFINITY_PRIORITY(args);

    THREAD_RUN_ATTACH_STATUS(args->instance_id, st);

    // Attach to paper_ouput_databuf
    THREAD_RUN_ATTACH_DATABUF(args->instance_id,
        paper_output_databuf, db, args->input_buffer);

    // Setup socket and message structures
    int sockfd;
    unsigned int xengine_id = 0;
    struct timespec packet_delay = {
      .tv_sec = 0,
      .tv_nsec = PACKET_DELAY_NS
    };

    guppi_status_lock_safe(&st);
    hgetu4(st.buf, "XID", &xengine_id); // No change if not found
    hputu4(st.buf, "XID", xengine_id);
    hputu4(st.buf, "OUTDUMPS", 0);
    guppi_status_unlock_safe(&st);

    pkt_t pkt;
    pkt.hdr.header = HEADER;
    pkt.hdr.instids = INSTIDS(xengine_id);
    pkt.hdr.pktinfo = PKTINFO(BYTES_PER_PACKET);
    pkt.hdr.heaplen = HEAPLEN;

    // TODO Get catcher hostname and port from somewhere

#ifndef CATCHER_PORT
#define CATCHER_PORT 7148
#endif
#define stringify2(x) #x
#define stringify(x) stringify2(x)

    // Open socket
    sockfd = open_udp_socket("catcher", stringify(CATCHER_PORT));
    if(sockfd == -1) {
        guppi_error(__FUNCTION__, "error opening socket");
        run_threads=0;
        pthread_exit(NULL);
    }

#ifdef TEST_INDEX_CALCS
    int i, j;
    for(i=0; i<32; i++) {
      for(j=i; j<32; j++) {
        regtile_index(2*i, 2*j);
      }
    }
    for(i=0; i<32; i++) {
      for(j=i; j<32; j++) {
        casper_index(2*i, 2*j);
      }
    }
    run_threads=0;
#endif

    /* Main loop */
    int rv;
    int casper_chan, gpu_chan;
    int baseline;
    unsigned int dumps = 0;
    int block_idx = 0;
    struct timespec start, stop;
    signal(SIGINT,cc);
    signal(SIGTERM,cc);
    while (run_threads) {

        guppi_status_lock_safe(&st);
        hputs(st.buf, STATUS_KEY, "waiting");
        guppi_status_unlock_safe(&st);

        // Wait for new block to be filled
        while ((rv=paper_output_databuf_wait_filled(db, block_idx))
                != GUPPI_OK) {
            if (rv==GUPPI_TIMEOUT) {
                guppi_status_lock_safe(&st);
                hputs(st.buf, STATUS_KEY, "blocked");
                guppi_status_unlock_safe(&st);
                continue;
            } else {
                guppi_error(__FUNCTION__, "error waiting for filled databuf");
                run_threads=0;
                pthread_exit(NULL);
                break;
            }
        }

        clock_gettime(CLOCK_MONOTONIC, &start);

        // Note processing status, current input block
        guppi_status_lock_safe(&st);
        hputs(st.buf, STATUS_KEY, "processing");
        hputi4(st.buf, "OUTBLKIN", block_idx);
        guppi_status_unlock_safe(&st);

        // Update header's timestamp for this dump
        pkt.hdr.timestamp = TIMESTAMP(db->block[block_idx].header.mcnt *
            N_TIME_PER_PACKET * 2 * N_CHAN_TOTAL / 128);

        // Init header's offset for this dump
        uint32_t nbytes = 0;
        pkt.hdr.offset = OFFSET(nbytes);

        // Unpack and convert in packet sized chunks
        float * pf_re  = db->block[block_idx].data;
        float * pf_im  = db->block[block_idx].data + xgpu_info.matLength;
        pktdata_t * p_out = pkt.data;
        for(casper_chan=0; casper_chan<N_CHAN_PER_X; casper_chan++) {
          // De-interleave the channels
          gpu_chan = (casper_chan/Nc) + ((casper_chan%Nc)*Nx);
          for(baseline=0; baseline<CASPER_CHAN_LENGTH; baseline++) {
            off_t idx_regtile = idx_map[baseline];
            pktdata_t re = CONVERT(pf_re[gpu_chan*REGTILE_CHAN_LENGTH+idx_regtile]);
            pktdata_t im = CONVERT(pf_im[gpu_chan*REGTILE_CHAN_LENGTH+idx_regtile]);
            *p_out++ = re;
            *p_out++ = -im; // Conjugate data to match downstream expectations
            nbytes += 2*sizeof(pktdata_t);
            if(nbytes % BYTES_PER_PACKET == 0) {
              int bytes_sent = send(sockfd, &pkt, sizeof(pkt.hdr)+BYTES_PER_PACKET, 0);
              if(bytes_sent == -1) {
                // Send all packets even if cactcher is not listening (i.e. we
                // we get a connection refused error), but abort sending this
                // dump if we get any other error.
                if(errno != ECONNREFUSED) {
                  perror("send");
                  // Update stats
                  guppi_status_lock_safe(&st);
                  hputu4(st.buf, "OUTDUMPS", ++dumps);
                  hputr4(st.buf, "OUTSECS", 0.0);
                  hputr4(st.buf, "OUTMBPS", 0.0);
                  guppi_status_unlock_safe(&st);
                  // Break out of both for loops
                  goto done_sending;
                }
              } else if(bytes_sent != sizeof(pkt.hdr)+BYTES_PER_PACKET) {
                printf("only sent %d of %lu bytes!!!\n", bytes_sent, sizeof(pkt.hdr)+BYTES_PER_PACKET);
              }

              // Delay to prevent overflowing network TX queue
              nanosleep(&packet_delay, NULL);

              // Setup for next packet
              p_out = pkt.data;
              // Update header's byte_offset for this chunk
              pkt.hdr.offset = OFFSET(nbytes);
            }
          }
        }

        clock_gettime(CLOCK_MONOTONIC, &stop);

        guppi_status_lock_safe(&st);
        hputu4(st.buf, "OUTDUMPS", ++dumps);
        hputr4(st.buf, "OUTSECS", (float)ELAPSED_NS(start,stop)/1e9);
        hputr4(st.buf, "OUTMBPS", (1e3*8*bytes_per_dump)/ELAPSED_NS(start,stop));
        guppi_status_unlock_safe(&st);

done_sending:

        // Mark block as free
        paper_output_databuf_set_free(db, block_idx);

        // Setup for next block
        block_idx = (block_idx + 1) % db->header.n_block;

        /* Will exit if thread has been cancelled */
        pthread_testcancel();
    }

    // Have to close all pushes
    THREAD_RUN_DETACH_DATAUF;
    THREAD_RUN_DETACH_STATUS;
    THREAD_RUN_END;

    // Thread success!
    return NULL;
}

static pipeline_thread_module_t module = {
    name: "paper_gpu_output_thread",
    type: PIPELINE_OUTPUT_THREAD,
    init: init,
    run:  run
};
        TIMESTAMP operator -(float seconds) const
		{ return TIMESTAMP(v - secsToTicks(seconds)); }
Beispiel #13
0
/**
 * Start timing
 *
 * Gets current timestamp and stores it in t
 */
void LpelTimingStart(lpel_timing_t *t)
{
  TIMESTAMP( t);
}
Beispiel #14
0
/**
 * Current timestamp
 *
 * Gets current timestamp and stores it in t
 */
void LpelTimingNow(lpel_timing_t *t)
{
  TIMESTAMP( t);
}