示例#1
0
/**************************************************************************//**
 * Read/skip data from the container.
 * Can also be used to query information about the next block of data.
 *
 * @param p_ctx      The reader context.
 * @param p_packet   The container packet information, or NULL.
 * @param flags      The container read flags.
 * @return  The resulting status of the function.
 */
static VC_CONTAINER_STATUS_T rtp_reader_read( VC_CONTAINER_T *p_ctx,
                                               VC_CONTAINER_PACKET_T *p_packet,
                                               uint32_t flags )
{
   VC_CONTAINER_TRACK_T *track;
   VC_CONTAINER_TRACK_MODULE_T *t_module;
   VC_CONTAINER_STATUS_T status;

   if((flags & VC_CONTAINER_READ_FLAG_FORCE_TRACK) && p_packet->track)
      return VC_CONTAINER_ERROR_INVALID_ARGUMENT;

   track = p_ctx->tracks[0];
   t_module = track->priv->module;

   CLEAR_BIT(t_module->flags, TRACK_NEW_PACKET);

   while (!BITS_AVAILABLE(p_ctx, &t_module->payload))
   {
      uint32_t bytes_read;

      /* No data left from last RTP packet, get another one */
      bytes_read = READ_BYTES(p_ctx, t_module->buffer, MAXIMUM_PACKET_SIZE);
      if (!bytes_read)
         return STREAM_STATUS(p_ctx);

      BITS_INIT(p_ctx, &t_module->payload, t_module->buffer, bytes_read);

      decode_rtp_packet_header(p_ctx, t_module);
      SET_BIT(t_module->flags, TRACK_NEW_PACKET);
   }

   if (p_packet)
   {
      uint32_t timestamp_top = t_module->timestamp >> 30;

      /* Determine whether timestamp has wrapped forwards or backwards around zero */
      if ((timestamp_top == 0) && (t_module->last_timestamp_top == 3))
         t_module->timestamp_wraps++;
      else if ((timestamp_top == 3) && (t_module->last_timestamp_top == 0))
         t_module->timestamp_wraps--;
      t_module->last_timestamp_top = timestamp_top;

      p_packet->dts = p_packet->pts = ((int64_t)t_module->timestamp_wraps << 32) | t_module->timestamp;
      p_packet->track = 0;
      p_packet->flags = 0;
   }

   status = t_module->payload_handler(p_ctx, track, p_packet, flags);
   if (p_packet && status == VC_CONTAINER_SUCCESS)
   {
      /* Adjust timestamps from RTP clock rate to microseconds */
      p_packet->pts = p_packet->pts * MICROSECONDS_PER_SECOND / t_module->timestamp_clock;
      p_packet->dts = p_packet->dts * MICROSECONDS_PER_SECOND / t_module->timestamp_clock;
   }

   STREAM_STATUS(p_ctx) = status;
   return status;
}
示例#2
0
static VC_CONTAINER_STATUS_T avi_finish_data_chunk( VC_CONTAINER_T *p_ctx, uint32_t chunk_size )
{
   VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
 
   if (chunk_size)
   {
      /* Rewrite the chunk size, this won't be efficient if it happens often */
      if (STREAM_SEEKABLE(p_ctx))
      {
         SEEK(p_ctx, STREAM_POSITION(p_ctx) - chunk_size - 4);
         WRITE_U32(p_ctx, chunk_size, "Chunk Size");
         SKIP_BYTES(p_ctx, chunk_size);
      }
      else
      {
         LOG_DEBUG(p_ctx, "warning, can't rewrite chunk size, data will be malformed");
         status = VC_CONTAINER_ERROR_FAILED;
      }
   }
      
   AVI_END_CHUNK(p_ctx);

   if (status != VC_CONTAINER_SUCCESS) status = STREAM_STATUS(p_ctx);

   return status;
}
示例#3
0
static VC_CONTAINER_STATUS_T avi_write_stream_format_chunk(VC_CONTAINER_T *p_ctx, 
   VC_CONTAINER_TRACK_T *track, uint32_t chunk_size)
{
   VC_CONTAINER_STATUS_T status;
   
   WRITE_FOURCC(p_ctx, VC_FOURCC('s','t','r','f'), "Chunk ID");
   WRITE_U32(p_ctx, chunk_size, "Chunk Size");
  
   if ((status = STREAM_STATUS(p_ctx)) != VC_CONTAINER_SUCCESS) return status;
  
   if(track->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO)
      status = vc_container_write_bitmapinfoheader(p_ctx, track->format);
   else if(track->format->es_type == VC_CONTAINER_ES_TYPE_AUDIO)
      status = vc_container_write_waveformatex(p_ctx, track->format);

   if (status != VC_CONTAINER_SUCCESS) return status;

   AVI_END_CHUNK(p_ctx);
   
   return STREAM_STATUS(p_ctx);
}
示例#4
0
/*****************************************************************************
Functions exported as part of the Container Module API
 *****************************************************************************/
static VC_CONTAINER_STATUS_T binary_reader_read( VC_CONTAINER_T *p_ctx,
   VC_CONTAINER_PACKET_T *packet, uint32_t flags )
{
   VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
   unsigned int size;

   if(module->status != VC_CONTAINER_SUCCESS)
      return module->status;

   if(!module->block_size)
   {
      module->block_size = module->default_block_size;
      module->init = 0;
   }

   packet->size = module->block_size;
   packet->dts = packet->pts = VC_CONTAINER_TIME_UNKNOWN;
   if(module->init) packet->dts = packet->pts = 0;
   packet->track = 0;
   packet->flags = 0;

   if(flags & VC_CONTAINER_READ_FLAG_SKIP)
   {
      size = SKIP_BYTES(p_ctx, module->block_size);
      module->block_size -= size;
      module->status = STREAM_STATUS(p_ctx);
      return module->status;
   }

   if(flags & VC_CONTAINER_READ_FLAG_INFO)
      return VC_CONTAINER_SUCCESS;

   size = MIN(module->block_size, packet->buffer_size);
   size = READ_BYTES(p_ctx, packet->data, size);
   module->block_size -= size;
   packet->size = size;

   module->status = size ? VC_CONTAINER_SUCCESS : STREAM_STATUS(p_ctx);
   return module->status;
}
示例#5
0
static VC_CONTAINER_STATUS_T ps_read_system_header( VC_CONTAINER_T *ctx )
{
   uint8_t header[8];
   uint32_t length;
   VC_CONTAINER_BITS_T bits;

   if(_READ_U32(ctx) != 0x1BB) return VC_CONTAINER_ERROR_CORRUPTED;
   LOG_FORMAT(ctx, "system_header");
   ctx->priv->module->level++;

   length = READ_U16(ctx, "header_length");
   if(length < 6) return VC_CONTAINER_ERROR_CORRUPTED;
   if(READ_BYTES(ctx, header, 6) != 6) return VC_CONTAINER_ERROR_EOS;

   BITS_INIT(ctx, &bits, header, 6);

   if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
   BITS_SKIP(ctx, &bits, 22, "rate_bound");
   if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
   BITS_SKIP(ctx, &bits, 6, "audio_bound");
   BITS_SKIP(ctx, &bits, 1, "fixed_flag");
   BITS_SKIP(ctx, &bits, 1, "CSPS_flag");
   BITS_SKIP(ctx, &bits, 1, "system_audio_lock_flag");
   BITS_SKIP(ctx, &bits, 1, "system_video_lock_flag");
   if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
   BITS_SKIP(ctx, &bits, 5, "video_bound");
   BITS_SKIP(ctx, &bits, 1, "packet_rate_restriction_flag");
   BITS_SKIP(ctx, &bits, 7, "reserved_bits");
   length -= 6;

   while(length >= 3 && (PEEK_U8(ctx) & 0x80))
   {
      SKIP_U8(ctx, "stream_id");
      SKIP_BYTES(ctx, 2);
      length -= 3;
   }
   SKIP_BYTES(ctx, length);

   ctx->priv->module->level--;
   return STREAM_STATUS(ctx);
}
示例#6
0
static VC_CONTAINER_STATUS_T rv9_read_file_header(VC_CONTAINER_T *p_ctx,
   VC_CONTAINER_TRACK_T *track)
{
   VC_CONTAINER_STATUS_T status;
   VC_CONTAINER_FOURCC_T codec;
   uint8_t dummy[12];
   uint32_t length;

   if(PEEK_BYTES(p_ctx, dummy, sizeof(dummy)) != sizeof(dummy)) return VC_CONTAINER_ERROR_EOS;

   length = BI32(dummy);
   if(length < 12 || length > 1024) return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;

   if(dummy[4] != 'V' || dummy[5] != 'I' || dummy[6] != 'D' || dummy[7] != 'O' ||
      dummy[8] != 'R' || dummy[9] != 'V' ||                    dummy[11] != '0')
      return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;

   switch(dummy[10]) {
   case '4': codec = VC_CONTAINER_CODEC_RV40; break;
   case '3': codec = VC_CONTAINER_CODEC_RV30; break;
   case '2': codec = VC_CONTAINER_CODEC_RV20; break;
   case '1': codec = VC_CONTAINER_CODEC_RV10; break;
   default: return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
   }

   if (!track)
      return VC_CONTAINER_SUCCESS;

   status = vc_container_track_allocate_extradata(p_ctx, track, length);
   if(status != VC_CONTAINER_SUCCESS) return status;

   if(READ_BYTES(p_ctx, track->format->extradata, length) != length) return VC_CONTAINER_ERROR_EOS;
   track->format->extradata_size = length;

   track->format->codec = codec;
   return STREAM_STATUS(p_ctx);
}
示例#7
0
static VC_CONTAINER_STATUS_T ps_read_pack_header( VC_CONTAINER_T *ctx )
{
   VC_CONTAINER_MODULE_T *module = ctx->priv->module;
   uint8_t header[10];
   int64_t scr, scr_base, scr_ext = INT64_C(0);
   uint64_t pack_offset = STREAM_POSITION(ctx);
   uint32_t mux_rate, stuffing;
   VC_CONTAINER_BITS_T bits;
   VC_CONTAINER_STATUS_T status;

   if(_READ_U32(ctx) != 0x1BA) return VC_CONTAINER_ERROR_CORRUPTED;
   LOG_FORMAT(ctx, "pack_header");
   
   module->level++;

   if (PEEK_U8(ctx) & 0x40)  /* program stream */
   {
      if(READ_BYTES(ctx, header, 10) != 10) return VC_CONTAINER_ERROR_EOS;
      BITS_INIT(ctx, &bits, header, 10);
      if(BITS_READ_U32(ctx, &bits, 2, "'01' marker bits") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      scr_base = BITS_READ_U32(ctx, &bits, 3, "system_clock_reference_base [32..30]") << 30;
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [29..15]") << 15;
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [14..0]");
      LOG_FORMAT(ctx, "system_clock_reference_base %"PRId64, scr_base);
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      scr_ext = BITS_READ_U32(ctx, &bits, 9, "system_clock_reference_extension");
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      mux_rate = BITS_READ_U32(ctx, &bits, 22, "program_mux_rate");
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      BITS_SKIP(ctx, &bits, 5, "reserved");
      stuffing = BITS_READ_U32(ctx, &bits, 3, "pack_stuffing_length");
      SKIP_BYTES(ctx, stuffing);
   }
   else /* system stream */
   {
      if(READ_BYTES(ctx, header, 8) != 8) return VC_CONTAINER_ERROR_EOS;
      BITS_INIT(ctx, &bits, header, 8);
      if(BITS_READ_U32(ctx, &bits, 4, "'0010' marker bits") != 0x2) return VC_CONTAINER_ERROR_CORRUPTED;
      scr_base = BITS_READ_U32(ctx, &bits, 3, "system_clock_reference_base [32..30]") << 30;
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [29..15]") << 15;
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [14..0]");
      LOG_FORMAT(ctx, "system_clock_reference_base %"PRId64, scr_base);
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
      mux_rate = BITS_READ_U32(ctx, &bits, 22, "program_mux_rate");
      if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED;
   }

   if ((status = STREAM_STATUS(ctx)) != VC_CONTAINER_SUCCESS) return status;
   
   module->level--;

   /* Set or update system_clock_reference, adjust bias if necessary */
   scr = scr_base * INT64_C(300) + scr_ext;

   if (module->scr_offset == VC_CONTAINER_TIME_UNKNOWN)
      module->scr_offset = scr;

   if (module->scr == VC_CONTAINER_TIME_UNKNOWN)
      module->scr_bias = -scr;
   else if (scr < module->scr)
      module->scr_bias = module->scr - scr;

   if (module->scr != VC_CONTAINER_TIME_UNKNOWN)
   {
      /* system_clock_reference is not necessarily continuous across the entire stream */
      if (scr > module->scr)
      {
         int64_t data_rate;
         data_rate = INT64_C(27000000) * (pack_offset - module->pack_offset) / (scr - module->scr);

         if (module->data_rate)
         {
            /* Simple moving average over data rate seen so far */
            module->data_rate = (module->data_rate * 31 + data_rate) >> 5;
         }
         else
         {