int media_send_video()

in libftl/media.c [645:767]


int media_send_video(ftl_stream_configuration_private_t *ftl, int64_t dts_usec, uint8_t *data, int32_t len, int end_of_frame) {
  ftl_media_component_common_t *mc = &ftl->video.media_component;
  uint8_t nalu_type = 0;
  uint8_t nri;
  int bytes_queued = 0;
  int pkt_len;
  int payload_size;
  nack_slot_t *slot;
  int remaining = len;
  int first_fu = 1;

  // Before we send any video we want to make sure the audio stream
  // is also ready to run. If the stream isn't ready drop this data.
  if (!ftl->audio.is_ready_to_send)
  {
    if (end_of_frame)
    {
      mc->stats.dropped_frames++;
    }
    return bytes_queued;
  }

  if (os_trylock_mutex(&ftl->video.mutex)) {

    if (ftl_get_state(ftl, FTL_MEDIA_READY)) {

      nalu_type = data[0] & 0x1F;
      nri = (data[0] >> 5) & 0x3;

      if (ftl->video.wait_for_idr_frame) {
        if (nalu_type == H264_NALU_TYPE_SPS) {

          ftl->video.wait_for_idr_frame = FALSE;

          if (!ftl->video.has_sent_first_frame) {
            FTL_LOG(ftl, FTL_LOG_INFO, "Audio is ready and we have the first iframe, starting stream. (dropped %d frames)\n", mc->stats.dropped_frames);
            ftl->video.has_sent_first_frame = TRUE;
          }
          else {
            FTL_LOG(ftl, FTL_LOG_INFO, "Got key frame, continuing (dropped %d frames)\n", mc->stats.dropped_frames);
          }
        }
        else {
          if (end_of_frame) {
            mc->stats.dropped_frames++;
          }
          os_unlock_mutex(&ftl->video.mutex);
          return bytes_queued;
        }
      }

      _update_timestamp(ftl, mc, dts_usec);

      if (nalu_type == H264_NALU_TYPE_IDR) {
        mc->tmp_seq_num = mc->seq_num;
      }

      while (remaining > 0) {
        uint16_t sn = mc->seq_num;
        uint32_t ssrc = mc->ssrc;
        uint8_t *pkt_buf;

        if ((slot = _media_get_empty_slot(ftl, ssrc, sn)) == NULL) {
          if (nri) {
            FTL_LOG(ftl, FTL_LOG_INFO, "Video queue full, dropping packets until next key frame\n");
            ftl->video.wait_for_idr_frame = TRUE;
          }
          os_unlock_mutex(&ftl->video.mutex);
          return bytes_queued;
        }       

        os_lock_mutex(&slot->mutex);

        pkt_buf = slot->packet;
        pkt_len = sizeof(slot->packet);

        slot->first = 0;
        slot->last = 0;

        payload_size = _media_make_video_rtp_packet(ftl, data, remaining, pkt_buf, &pkt_len, first_fu);

        first_fu = 0;
        remaining -= payload_size;
        data += payload_size;
        bytes_queued += pkt_len;
        mc->stats.payload_bytes_sent += payload_size;

        /*if all data has been consumed set marker bit*/
        if (remaining <= 0 && end_of_frame) {
          _media_set_marker_bit(mc, pkt_buf);
          slot->last = 1;
        }

        slot->len = pkt_len;
        slot->sn = sn;
        gettimeofday(&slot->insert_time, NULL);
        slot->isPartOfIframe = nalu_type == H264_NALU_TYPE_IDR;

        os_unlock_mutex(&slot->mutex);
        os_semaphore_post(&mc->pkt_ready);

        mc->stats.packets_queued++;
        mc->stats.bytes_queued += pkt_len;
      }

      mc->stats.current_frame_size += len;

      if (end_of_frame) {
        mc->stats.frames_received++;

        if (mc->stats.current_frame_size > mc->stats.max_frame_size) {
          mc->stats.max_frame_size = mc->stats.current_frame_size;
        }

        mc->stats.current_frame_size = 0;
      }
    }

    os_unlock_mutex(&ftl->video.mutex);
  }

  return bytes_queued;
}