Esempio n. 1
0
GstBuffer *
mpegtsmux_prepare_aac (GstBuffer * buf, MpegTsPadData * data, MpegTsMux * mux)
{
  guint8 adts_header[7] = { 0, };
  GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 7);
  gsize out_offset = 0;
  guint8 rate_idx = 0, channels = 0, obj_type = 0;

  GST_DEBUG_OBJECT (mux, "Preparing AAC buffer for output");

  /* We want the same metadata */
  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);

  /* Generate ADTS header */
  obj_type = (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data)) & 0xC) >> 2;
  obj_type++;
  rate_idx = (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data)) & 0x3) << 1;
  rate_idx |=
      (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + 1) & 0x80) >> 7;
  channels =
      (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + 1) & 0x78) >> 3;
  GST_DEBUG_OBJECT (mux, "Rate index %u, channels %u, object type %u", rate_idx,
      channels, obj_type);
  /* Sync point over a full byte */
  adts_header[0] = 0xFF;
  /* Sync point continued over first 4 bits + static 4 bits
   * (ID, layer, protection)*/
  adts_header[1] = 0xF1;
  /* Object type over first 2 bits */
  adts_header[2] = obj_type << 6;
  /* rate index over next 4 bits */
  adts_header[2] |= (rate_idx << 2);
  /* channels over last 2 bits */
  adts_header[2] |= (channels & 0x4) >> 2;
  /* channels continued over next 2 bits + 4 bits at zero */
  adts_header[3] = (channels & 0x3) << 6;
  /* frame size over last 2 bits */
  adts_header[3] |= (GST_BUFFER_SIZE (out_buf) & 0x1800) >> 11;
  /* frame size continued over full byte */
  adts_header[4] = (GST_BUFFER_SIZE (out_buf) & 0x1FF8) >> 3;
  /* frame size continued first 3 bits */
  adts_header[5] = (GST_BUFFER_SIZE (out_buf) & 0x7) << 5;
  /* buffer fullness (0x7FF for VBR) over 5 last bits */
  adts_header[5] |= 0x1F;
  /* buffer fullness (0x7FF for VBR) continued over 6 first bits + 2 zeros for
   * number of raw data blocks */
  adts_header[6] = 0xFC;

  /* Insert ADTS header */
  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, adts_header, 7);
  out_offset += 7;

  /* Now copy complete frame */
  memcpy (GST_BUFFER_DATA (out_buf) + out_offset, GST_BUFFER_DATA (buf),
      GST_BUFFER_SIZE (buf));

  return out_buf;
}
Esempio n. 2
0
static GstFlowReturn
gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
{
  guint8 *buf;

  gint len_mask = 0x80, read = 1, n = 1;

  guint32 total;

  guint8 b;

  GstFlowReturn ret;

  ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
  if (ret != GST_FLOW_OK)
    return ret;

  b = GST_READ_UINT8 (buf);

  total = (guint32) b;

  while (read <= 4 && !(total & len_mask)) {
    read++;
    len_mask >>= 1;
  }
  if (read > 4) {
    guint64 pos = ebml->offset;

    GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
        ("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT
            " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
    return GST_FLOW_ERROR;
  }

  ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
  if (ret != GST_FLOW_OK)
    return ret;

  while (n < read) {
    b = GST_READ_UINT8 (buf + n);
    total = (total << 8) | b;
    ++n;
  }

  *id = total;

  /* level */
  if (level_up)
    *level_up = gst_ebml_read_element_level_up (ebml);

  ebml->offset += read;
  return GST_FLOW_OK;
}
Esempio n. 3
0
static void
check_rgb_buf (const guint8 * pixels, guint32 r_mask, guint32 g_mask,
    guint32 b_mask, guint32 a_mask, guint8 r_expected, guint8 g_expected,
    guint8 b_expected, guint bpp, guint depth)
{
  guint32 pixel, red, green, blue, alpha;

  switch (bpp) {
    case 32:
      pixel = GST_READ_UINT32_BE (pixels);
      break;
    case 24:
      pixel = (GST_READ_UINT8 (pixels) << 16) |
          (GST_READ_UINT8 (pixels + 1) << 8) |
          (GST_READ_UINT8 (pixels + 2) << 0);
      break;
    case 16:
      if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
        pixel = GST_READ_UINT16_LE (pixels);
      else
        pixel = GST_READ_UINT16_BE (pixels);
      break;
    default:
      g_return_if_reached ();
  }

  red = right_shift_colour (r_mask, pixel);
  green = right_shift_colour (g_mask, pixel);
  blue = right_shift_colour (b_mask, pixel);
  alpha = right_shift_colour (a_mask, pixel);

  /* can't enable this by default, valgrind will complain about accessing
   * uninitialised memory for the depth=24,bpp=32 formats ... */
  /* GST_LOG ("pixels: 0x%02x 0x%02x 0x%02x 0x%02x => pixel = 0x%08x",
     pixels[0], (guint) pixels[1], pixels[2], pixels[3], pixel); */

  /* fix up the mask (for rgb15/16) */
  if (bpp == 16) {
    r_expected = fix_expected_colour (r_mask, r_expected);
    g_expected = fix_expected_colour (g_mask, g_expected);
    b_expected = fix_expected_colour (b_mask, b_expected);
  }

  fail_unless (red == r_expected, "RED: expected 0x%02x, found 0x%02x",
      r_expected, red);
  fail_unless (green == g_expected, "GREEN: expected 0x%02x, found 0x%02x",
      g_expected, green);
  fail_unless (blue == b_expected, "BLUE: expected 0x%02x, found 0x%02x",
      b_expected, blue);

  fail_unless (a_mask == 0 || alpha != 0);      /* better than nothing */
}
/* inspired by the original one in wavpack */
gboolean
gst_wavpack_read_metadata (GstWavpackMetadata * wpmd, guint8 * header_data,
    guint8 ** p_data)
{
  WavpackHeader hdr;
  guint8 *end;

  gst_wavpack_read_header (&hdr, header_data);
  end = header_data + hdr.ckSize + 8;

  if (end - *p_data < 2)
    return FALSE;

  wpmd->id = GST_READ_UINT8 (*p_data);
  wpmd->byte_length = 2 * (guint) GST_READ_UINT8 (*p_data + 1);

  *p_data += 2;

  if ((wpmd->id & ID_LARGE) == ID_LARGE) {
    guint extra;

    wpmd->id &= ~ID_LARGE;

    if (end - *p_data < 2)
      return FALSE;

    extra = GST_READ_UINT16_LE (*p_data);
    wpmd->byte_length += (extra << 9);
    *p_data += 2;
  }

  if ((wpmd->id & ID_ODD_SIZE) == ID_ODD_SIZE) {
    wpmd->id &= ~ID_ODD_SIZE;
    --wpmd->byte_length;
  }

  if (wpmd->byte_length > 0) {
    if (end - *p_data < wpmd->byte_length + (wpmd->byte_length & 1)) {
      wpmd->data = NULL;
      return FALSE;
    }

    wpmd->data = *p_data;
    *p_data += wpmd->byte_length + (wpmd->byte_length & 1);
  } else {
    wpmd->data = NULL;
  }

  return TRUE;
}
Esempio n. 5
0
/* parses the first CMML packet (the ident header)
 */
static void
gst_cmml_dec_parse_ident_header (GstCmmlDec * dec, GstBuffer * buffer)
{
  guint8 *data = GST_BUFFER_DATA (buffer);

  /* the ident header has a fixed length */
  if (GST_BUFFER_SIZE (buffer) != CMML_IDENT_HEADER_SIZE) {
    GST_ELEMENT_ERROR (dec, STREAM, DECODE,
        (NULL), ("wrong ident header size: %d", GST_BUFFER_SIZE (buffer)));
    dec->flow_return = GST_FLOW_ERROR;

    return;
  }

  data += 8;
  dec->major = GST_READ_UINT16_LE (data);
  data += 2;
  dec->minor = GST_READ_UINT16_LE (data);
  data += 2;
  dec->granulerate_n = GST_READ_UINT64_LE (data);
  data += 8;
  dec->granulerate_d = GST_READ_UINT64_LE (data);
  data += 8;
  dec->granuleshift = GST_READ_UINT8 (data);

  GST_INFO_OBJECT (dec, "bitstream initialized "
      "(major: %" G_GINT16_FORMAT " minor: %" G_GINT16_FORMAT
      " granulerate_n: %" G_GINT64_FORMAT " granulerate_d: %" G_GINT64_FORMAT
      " granuleshift: %d)",
      dec->major, dec->minor,
      dec->granulerate_n, dec->granulerate_d, dec->granuleshift);

  dec->flow_return = GST_FLOW_OK;
}
Esempio n. 6
0
gboolean
mxf_product_version_parse (MXFProductVersion * product_version,
    const guint8 * data, guint size)
{
  g_return_val_if_fail (product_version != NULL, FALSE);
  g_return_val_if_fail (data != NULL, FALSE);

  memset (product_version, 0, sizeof (MXFProductVersion));

  if (size < 9)
    return FALSE;

  product_version->major = GST_READ_UINT16_BE (data);
  product_version->minor = GST_READ_UINT16_BE (data + 2);
  product_version->patch = GST_READ_UINT16_BE (data + 4);
  product_version->build = GST_READ_UINT16_BE (data + 6);

  /* Avid writes a 9 byte product version */
  if (size == 9)
    product_version->release = GST_READ_UINT8 (data + 8);
  else
    product_version->release = GST_READ_UINT16_BE (data + 8);

  return TRUE;
}
Esempio n. 7
0
static GstFlowReturn
gst_mve_video_palette_compressed (GstMveDemux * mve, const guint8 * data,
    guint16 len)
{
  guint8 mask;
  gint i, j;
  guint32 *col;

  GST_DEBUG_OBJECT (mve, "compressed video palette");

  if (mve->video_stream == NULL) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("found palette before video stream was initialized"));
    return GST_FLOW_ERROR;
  }

  if (mve->video_stream->palette == NULL) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("no palette available for modification"));
    return GST_FLOW_ERROR;
  }

  /* need at least 32 more bytes */
  if (len < 32)
    return gst_mve_stream_error (mve, 32, len);

  len -= 32;

  for (i = 0; i < 32; ++i) {
    mask = GST_READ_UINT8 (data);
    ++data;

    if (mask != 0) {
      for (j = 0; j < 8; ++j) {
        if (mask & (1 << j)) {
          guint8 r, g, b;

          /* need 3 more bytes */
          if (len < 3)
            return gst_mve_stream_error (mve, 3, len);

          len -= 3;

          r = (*data) << 2;
          ++data;
          g = (*data) << 2;
          ++data;
          b = (*data) << 2;
          ++data;
          col =
              ((guint32 *) GST_BUFFER_DATA (mve->video_stream->palette)) +
              i * 8 + j;
          *col = (r << 16) | (g << 8) | (b);
        }
      }
    }
  }

  return GST_FLOW_OK;
}
static gpointer
_parse_atsc_stt (GstMpegtsSection * section)
{
    GstMpegtsAtscSTT *stt = NULL;
    guint8 *data, *end;
    guint16 daylight_saving;

    stt = g_slice_new0 (GstMpegtsAtscSTT);

    data = section->data;
    end = data + section->section_length;

    /* Skip already parsed data */
    data += 8;

    stt->protocol_version = GST_READ_UINT8 (data);
    data += 1;
    stt->system_time = GST_READ_UINT32_BE (data);
    data += 4;
    stt->gps_utc_offset = GST_READ_UINT8 (data);
    data += 1;

    daylight_saving = GST_READ_UINT16_BE (data);
    data += 2;
    stt->ds_status = daylight_saving >> 15;
    stt->ds_dayofmonth = (daylight_saving >> 8) & 0x1F;
    stt->ds_hour = daylight_saving & 0xFF;

    stt->descriptors = gst_mpegts_parse_descriptors (data, end - data - 4);
    if (stt->descriptors == NULL)
        goto error;

    return (gpointer) stt;

error:
    _gst_mpegts_atsc_stt_free (stt);

    return NULL;
}
Esempio n. 9
0
static gboolean
handle_buffer (GstRtpOnvifParse * self, GstBuffer * buf)
{
  GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
  guint8 *data;
  guint16 bits;
  guint wordlen;
  guint8 flags;
  /*
     guint64 timestamp;
     guint8 cseq;
   */

  if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp)) {
    GST_ELEMENT_ERROR (self, STREAM, FAILED,
        ("Failed to map RTP buffer"), (NULL));
    return FALSE;
  }

  /* Check if the ONVIF RTP extension is present in the packet */
  if (!gst_rtp_buffer_get_extension_data (&rtp, &bits, (gpointer) & data,
          &wordlen))
    goto out;

  if (bits != EXTENSION_ID || wordlen != EXTENSION_SIZE)
    goto out;

  /* timestamp = GST_READ_UINT64_BE (data);  TODO */
  flags = GST_READ_UINT8 (data + 8);
  /* cseq = GST_READ_UINT8 (data + 9);  TODO */

  /* C */
  if (flags & (1 << 7))
    GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
  else
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);

  /* E */
  /* if (flags & (1 << 6));  TODO */

  /* D */
  if (flags & (1 << 5))
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
  else
    GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);

out:
  gst_rtp_buffer_unmap (&rtp);
  return TRUE;
}
Esempio n. 10
0
EXPORT_C
#endif


gboolean
gst_byte_reader_peek_int8 (GstByteReader * reader, gint8 * val)
{
  g_return_val_if_fail (reader != NULL, FALSE);
  g_return_val_if_fail (val != NULL, FALSE);

  if (reader->byte >= reader->size)
    return FALSE;

  *val = GST_READ_UINT8 (&reader->data[reader->byte]);
  return TRUE;
}
Esempio n. 11
0
gboolean
gst_asf_demux_parse_packet (GstASFDemux * demux, GstBuffer * buf)
{
  AsfPacket packet = { 0, };
  const guint8 *data;
  gboolean has_multiple_payloads;
  gboolean ret = TRUE;
  guint8 ec_flags, flags1;
  guint size;

  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);
  GST_LOG_OBJECT (demux, "Buffer size: %u", size);

  /* need at least two payload flag bytes, send time, and duration */
  if (G_UNLIKELY (size < 2 + 4 + 2))
    goto short_packet;

  packet.buf = buf;

  ec_flags = GST_READ_UINT8 (data);

  /* skip optional error correction stuff */
  if ((ec_flags & 0x80) != 0) {
    guint ec_len_type, ec_len;

    ec_len_type = (ec_flags & 0x60) >> 5;
    if (ec_len_type == 0) {
      ec_len = ec_flags & 0x0f;
    } else {
      GST_WARNING_OBJECT (demux, "unexpected error correction length type %u",
          ec_len_type);
      ec_len = 2;
    }
    GST_LOG_OBJECT (demux, "packet has error correction (%u bytes)", ec_len);

    /* still need at least two payload flag bytes, send time, and duration */
    if (size <= (1 + ec_len) + 2 + 4 + 2)
      goto short_packet;

    data += 1 + ec_len;
    size -= 1 + ec_len;
  }
Esempio n. 12
0
gchar *
gst_rm_utils_read_string8 (const guint8 * data, guint datalen,
    guint * p_total_len)
{
  gint length;

  if (p_total_len)
    *p_total_len = 0;

  if (datalen < 1)
    return NULL;

  length = GST_READ_UINT8 (data);
  if (datalen < (1 + length))
    return NULL;

  if (p_total_len)
    *p_total_len = 1 + length;

  return g_strndup ((gchar *) data + 1, length);
}
static gpointer
_parse_ett (GstMpegtsSection * section)
{
    GstMpegtsAtscETT *ett = NULL;
    guint8 *data, *end;

    ett = g_slice_new0 (GstMpegtsAtscETT);

    data = section->data;
    end = data + section->section_length;

    ett->ett_table_id_extension = section->subtable_extension;

    /* Skip already parsed data */
    data += 8;

    ett->protocol_version = GST_READ_UINT8 (data);
    data += 1;
    ett->etm_id = GST_READ_UINT32_BE (data);
    data += 4;

    ett->messages = _parse_atsc_mult_string (data, end - data - 4);
    data += end - data - 4;

    if (data != end - 4) {
        GST_WARNING ("PID %d invalid ETT parsed %d length %d",
                     section->pid, (gint) (data - section->data), section->section_length);
        goto error;
    }

    return (gpointer) ett;

error:
    _gst_mpegts_atsc_ett_free (ett);

    return NULL;

}
Esempio n. 14
0
/* we are unlikely to deal with lengths > 2GB here any time soon, so just
 * return a signed int and use that for error reporting */
static inline gint
asf_packet_read_varlen_int (guint lentype_flags, guint lentype_bit_offset,
    const guint8 ** p_data, guint * p_size)
{
  static const guint lens[4] = { 0, 1, 2, 4 };
  guint len, val;

  len = lens[(lentype_flags >> lentype_bit_offset) & 0x03];

  /* will make caller bail out with a short read if there's not enough data */
  if (G_UNLIKELY (*p_size < len)) {
    GST_WARNING ("need %u bytes, but only %u bytes available", len, *p_size);
    return -1;
  }

  switch (len) {
    case 0:
      val = 0;
      break;
    case 1:
      val = GST_READ_UINT8 (*p_data);
      break;
    case 2:
      val = GST_READ_UINT16_LE (*p_data);
      break;
    case 4:
      val = GST_READ_UINT32_LE (*p_data);
      break;
    default:
      g_assert_not_reached ();
  }

  *p_data += len;
  *p_size -= len;

  return (gint) val;
}
Esempio n. 15
0
gboolean
mxf_timestamp_parse (MXFTimestamp * timestamp, const guint8 * data, guint size)
{
  g_return_val_if_fail (data != NULL, FALSE);
  g_return_val_if_fail (timestamp != NULL, FALSE);

  memset (timestamp, 0, sizeof (MXFTimestamp));

  if (size < 8)
    return FALSE;

  timestamp->year = GST_READ_UINT16_BE (data);
  timestamp->month = GST_READ_UINT8 (data + 2);
  timestamp->day = GST_READ_UINT8 (data + 3);
  timestamp->hour = GST_READ_UINT8 (data + 4);
  timestamp->minute = GST_READ_UINT8 (data + 5);
  timestamp->second = GST_READ_UINT8 (data + 6);
  timestamp->quarter_msecond = GST_READ_UINT8 (data + 7);

  return TRUE;
}
Esempio n. 16
0
static gboolean
gst_asf_demux_parse_payload (GstASFDemux * demux, AsfPacket * packet,
    gint lentype, const guint8 ** p_data, guint * p_size)
{
  AsfPayload payload = { 0, };
  AsfStream *stream;
  gboolean is_compressed;
  guint payload_len;
  guint stream_num;

  if (G_UNLIKELY (*p_size < 1)) {
    GST_WARNING_OBJECT (demux, "Short packet!");
    return FALSE;
  }

  stream_num = GST_READ_UINT8 (*p_data) & 0x7f;
  payload.keyframe = ((GST_READ_UINT8 (*p_data) & 0x80) != 0);

  *p_data += 1;
  *p_size -= 1;

  payload.ts = GST_CLOCK_TIME_NONE;
  payload.duration = GST_CLOCK_TIME_NONE;
  payload.par_x = 0;
  payload.par_y = 0;
  payload.interlaced = FALSE;
  payload.tff = FALSE;
  payload.rff = FALSE;

  payload.mo_number =
      asf_packet_read_varlen_int (packet->prop_flags, 4, p_data, p_size);
  payload.mo_offset =
      asf_packet_read_varlen_int (packet->prop_flags, 2, p_data, p_size);
  payload.rep_data_len =
      asf_packet_read_varlen_int (packet->prop_flags, 0, p_data, p_size);

  is_compressed = (payload.rep_data_len == 1);

  GST_LOG_OBJECT (demux, "payload for stream %u", stream_num);
  GST_LOG_OBJECT (demux, "keyframe   : %s", (payload.keyframe) ? "yes" : "no");
  GST_LOG_OBJECT (demux, "compressed : %s", (is_compressed) ? "yes" : "no");

  if (G_UNLIKELY (*p_size < payload.rep_data_len)) {
    GST_WARNING_OBJECT (demux, "Short packet! rep_data_len=%u, size=%u",
        payload.rep_data_len, *p_size);
    return FALSE;
  }

  memcpy (payload.rep_data, *p_data,
      MIN (sizeof (payload.rep_data), payload.rep_data_len));

  *p_data += payload.rep_data_len;
  *p_size -= payload.rep_data_len;

  if (G_UNLIKELY (*p_size == 0)) {
    GST_WARNING_OBJECT (demux, "payload without data!?");
    return FALSE;
  }

  /* we use -1 as lentype for a single payload that's the size of the packet */
  if (G_UNLIKELY ((lentype >= 0 && lentype <= 3))) {
    payload_len = asf_packet_read_varlen_int (lentype, 0, p_data, p_size);
    if (*p_size < payload_len) {
      GST_WARNING_OBJECT (demux, "Short packet! payload_len=%u, size=%u",
          payload_len, *p_size);
      return FALSE;
    }
  } else {
    payload_len = *p_size;
  }

  GST_LOG_OBJECT (demux, "payload length: %u", payload_len);

  stream = gst_asf_demux_get_stream (demux, stream_num);

  if (G_UNLIKELY (stream == NULL)) {
    GST_WARNING_OBJECT (demux, "Payload for unknown stream %u, skipping",
        stream_num);
    if (*p_size < payload_len) {
      *p_data += *p_size;
      *p_size = 0;
    } else {
      *p_data += payload_len;
      *p_size -= payload_len;
    }
    return TRUE;
  }

  if (G_UNLIKELY (!is_compressed)) {
    GST_LOG_OBJECT (demux, "replicated data length: %u", payload.rep_data_len);

    if (payload.rep_data_len >= 8) {
      payload.mo_size = GST_READ_UINT32_LE (payload.rep_data);
      payload.ts = GST_READ_UINT32_LE (payload.rep_data + 4) * GST_MSECOND;
      if (G_UNLIKELY (payload.ts < demux->preroll))
        payload.ts = 0;
      else
        payload.ts -= demux->preroll;
      asf_payload_parse_replicated_data_extensions (stream, &payload);

      GST_LOG_OBJECT (demux, "media object size   : %u", payload.mo_size);
      GST_LOG_OBJECT (demux, "media object ts     : %" GST_TIME_FORMAT,
          GST_TIME_ARGS (payload.ts));
      GST_LOG_OBJECT (demux, "media object dur    : %" GST_TIME_FORMAT,
          GST_TIME_ARGS (payload.duration));
    } else if (payload.rep_data_len != 0) {
      GST_WARNING_OBJECT (demux, "invalid replicated data length, very bad");
      *p_data += payload_len;
      *p_size -= payload_len;
      return FALSE;
    }

    GST_LOG_OBJECT (demux, "media object offset : %u", payload.mo_offset);

    GST_LOG_OBJECT (demux, "payload length: %u", payload_len);

    if ((stream = gst_asf_demux_get_stream (demux, stream_num))
        && payload_len) {
      payload.buf = asf_packet_create_payload_buffer (packet, p_data, p_size,
          payload_len);

      /* n-th fragment of a fragmented media object? */
      if (payload.mo_offset != 0) {
        AsfPayload *prev;

        if ((prev = asf_payload_find_previous_fragment (&payload, stream))) {
          if (payload.mo_offset != GST_BUFFER_SIZE (prev->buf)) {
            GST_WARNING_OBJECT (demux, "Offset doesn't match previous data?!");
          }
          /* note: buffer join/merge might not preserve buffer flags */
          prev->buf = gst_buffer_join (prev->buf, payload.buf);
          GST_LOG_OBJECT (demux, "Merged fragments, merged size: %u",
              GST_BUFFER_SIZE (prev->buf));
        } else {
          gst_buffer_unref (payload.buf);
        }
        payload.buf = NULL;
      } else {
        gst_asf_payload_queue_for_stream (demux, &payload, stream);
      }
    }
  } else {
    const guint8 *payload_data;
    GstClockTime ts, ts_delta;
    guint num;

    GST_LOG_OBJECT (demux, "Compressed payload, length=%u", payload_len);

    payload_data = *p_data;

    *p_data += payload_len;
    *p_size -= payload_len;

    ts = payload.mo_offset * GST_MSECOND;
    if (G_UNLIKELY (ts < demux->preroll))
      ts = 0;
    else
      ts -= demux->preroll;
    ts_delta = payload.rep_data[0] * GST_MSECOND;

    for (num = 0; payload_len > 0; ++num) {
      guint sub_payload_len;

      sub_payload_len = GST_READ_UINT8 (payload_data);

      GST_LOG_OBJECT (demux, "subpayload #%u: len=%u, ts=%" GST_TIME_FORMAT,
          num, sub_payload_len, GST_TIME_ARGS (ts));

      ++payload_data;
      --payload_len;

      if (G_UNLIKELY (payload_len < sub_payload_len)) {
        GST_WARNING_OBJECT (demux, "Short payload! %u bytes left", payload_len);
        return FALSE;
      }

      if (G_LIKELY (sub_payload_len > 0)) {
        payload.buf = asf_packet_create_payload_buffer (packet,
            &payload_data, &payload_len, sub_payload_len);

        payload.ts = ts;
        if (G_LIKELY (ts_delta))
          payload.duration = ts_delta;
        else
          payload.duration = GST_CLOCK_TIME_NONE;

        gst_asf_payload_queue_for_stream (demux, &payload, stream);
      }

      ts += ts_delta;
    }
  }

  return TRUE;
}
Esempio n. 17
0
      GST_WARNING_OBJECT (demux, "unexpected error correction length type %u",
          ec_len_type);
      ec_len = 2;
    }
    GST_LOG_OBJECT (demux, "packet has error correction (%u bytes)", ec_len);

    /* still need at least two payload flag bytes, send time, and duration */
    if (size <= (1 + ec_len) + 2 + 4 + 2)
      goto short_packet;

    data += 1 + ec_len;
    size -= 1 + ec_len;
  }

  /* parse payload info */
  flags1 = GST_READ_UINT8 (data);
  packet.prop_flags = GST_READ_UINT8 (data + 1);

  data += 2;
  size -= 2;

  has_multiple_payloads = (flags1 & 0x01) != 0;

  packet.length = asf_packet_read_varlen_int (flags1, 5, &data, &size);

  packet.sequence = asf_packet_read_varlen_int (flags1, 1, &data, &size);

  packet.padding = asf_packet_read_varlen_int (flags1, 3, &data, &size);

  if (G_UNLIKELY (size < 6))
    goto short_packet;
Esempio n. 18
0
/* SMPTE 377M 10.2.3 */
gboolean
mxf_index_table_segment_parse (const MXFUL * key,
    MXFIndexTableSegment * segment, const MXFPrimerPack * primer,
    const guint8 * data, guint size)
{
#ifndef GST_DISABLE_GST_DEBUG
  gchar str[48];
#endif
  guint16 tag, tag_size;
  const guint8 *tag_data;

  g_return_val_if_fail (key != NULL, FALSE);
  g_return_val_if_fail (data != NULL, FALSE);
  g_return_val_if_fail (primer != NULL, FALSE);

  memset (segment, 0, sizeof (MXFIndexTableSegment));

  if (size < 70)
    return FALSE;

  GST_DEBUG ("Parsing index table segment:");

  while (mxf_local_tag_parse (data, size, &tag, &tag_size, &tag_data)) {
    if (tag_size == 0 || tag == 0x0000)
      goto next;

    switch (tag) {
      case 0x3c0a:
        if (tag_size != 16)
          goto error;
        memcpy (&segment->instance_id, tag_data, 16);
        GST_DEBUG ("  instance id = %s",
            mxf_ul_to_string (&segment->instance_id, str));
        break;
      case 0x3f0b:
        if (!mxf_fraction_parse (&segment->index_edit_rate, tag_data, tag_size))
          goto error;
        GST_DEBUG ("  index edit rate = %d/%d", segment->index_edit_rate.n,
            segment->index_edit_rate.d);
        break;
      case 0x3f0c:
        if (tag_size != 8)
          goto error;
        segment->index_start_position = GST_READ_UINT64_BE (tag_data);
        GST_DEBUG ("  index start position = %" G_GINT64_FORMAT,
            segment->index_start_position);
        break;
      case 0x3f0d:
        if (tag_size != 8)
          goto error;
        segment->index_duration = GST_READ_UINT64_BE (tag_data);
        GST_DEBUG ("  index duration = %" G_GINT64_FORMAT,
            segment->index_duration);
        break;
      case 0x3f05:
        if (tag_size != 4)
          goto error;
        segment->edit_unit_byte_count = GST_READ_UINT32_BE (tag_data);
        GST_DEBUG ("  edit unit byte count = %u",
            segment->edit_unit_byte_count);
        break;
      case 0x3f06:
        if (tag_size != 4)
          goto error;
        segment->index_sid = GST_READ_UINT32_BE (tag_data);
        GST_DEBUG ("  index sid = %u", segment->index_sid);
        break;
      case 0x3f07:
        if (tag_size != 4)
          goto error;
        segment->body_sid = GST_READ_UINT32_BE (tag_data);
        GST_DEBUG ("  body sid = %u", segment->body_sid);
        break;
      case 0x3f08:
        if (tag_size != 1)
          goto error;
        segment->slice_count = GST_READ_UINT8 (tag_data);
        GST_DEBUG ("  slice count = %u", segment->slice_count);
        break;
      case 0x3f0e:
        if (tag_size != 1)
          goto error;
        segment->pos_table_count = GST_READ_UINT8 (tag_data);
        GST_DEBUG ("  pos table count = %u", segment->pos_table_count);
        break;
      case 0x3f09:{
        guint len, i;

        if (tag_size < 8)
          goto error;

        len = GST_READ_UINT32_BE (tag_data);
        segment->n_delta_entries = len;
        GST_DEBUG ("  number of delta entries = %u", segment->n_delta_entries);
        if (len == 0)
          goto next;
        tag_data += 4;
        tag_size -= 4;

        if (GST_READ_UINT32_BE (tag_data) != 6)
          goto error;

        tag_data += 4;
        tag_size -= 4;

        if (tag_size < len * 6)
          goto error;

        segment->delta_entries = g_new (MXFDeltaEntry, len);

        for (i = 0; i < len; i++) {
          GST_DEBUG ("    delta entry %u:", i);

          segment->delta_entries[i].pos_table_index = GST_READ_UINT8 (tag_data);
          tag_data += 1;
          tag_size -= 1;
          GST_DEBUG ("    pos table index = %d",
              segment->delta_entries[i].pos_table_index);

          segment->delta_entries[i].slice = GST_READ_UINT8 (tag_data);
          tag_data += 1;
          tag_size -= 1;
          GST_DEBUG ("    slice = %u", segment->delta_entries[i].slice);

          segment->delta_entries[i].element_delta =
              GST_READ_UINT32_BE (tag_data);
          tag_data += 4;
          tag_size -= 4;
          GST_DEBUG ("    element delta = %u",
              segment->delta_entries[i].element_delta);
        }
        break;
      }
      case 0x3f0a:{
        guint len, i, j;

        if (tag_size < 8)
          goto error;

        len = GST_READ_UINT32_BE (tag_data);
        segment->n_index_entries = len;
        GST_DEBUG ("  number of index entries = %u", segment->n_index_entries);
        if (len == 0)
          goto next;
        tag_data += 4;
        tag_size -= 4;

        if (GST_READ_UINT32_BE (tag_data) !=
            (11 + 4 * segment->slice_count + 8 * segment->pos_table_count))
          goto error;

        tag_data += 4;
        tag_size -= 4;

        if (tag_size <
            len * (11 + 4 * segment->slice_count +
                8 * segment->pos_table_count))
          goto error;

        segment->index_entries = g_new (MXFIndexEntry, len);

        for (i = 0; i < len; i++) {
          MXFIndexEntry *entry = &segment->index_entries[i];

          GST_DEBUG ("    index entry %u:", i);

          entry->temporal_offset = GST_READ_UINT8 (tag_data);
          tag_data += 1;
          tag_size -= 1;
          GST_DEBUG ("    temporal offset = %d", entry->temporal_offset);

          entry->key_frame_offset = GST_READ_UINT8 (tag_data);
          tag_data += 1;
          tag_size -= 1;
          GST_DEBUG ("    keyframe offset = %d", entry->key_frame_offset);

          entry->flags = GST_READ_UINT8 (tag_data);
          tag_data += 1;
          tag_size -= 1;
          GST_DEBUG ("    flags = 0x%02x", entry->flags);

          entry->stream_offset = GST_READ_UINT64_BE (tag_data);
          tag_data += 8;
          tag_size -= 8;
          GST_DEBUG ("    stream offset = %" G_GUINT64_FORMAT,
              entry->stream_offset);

          for (j = 0; j < segment->slice_count; j++) {
            entry->slice_offset[j] = GST_READ_UINT32_BE (tag_data);
            tag_data += 4;
            tag_size -= 4;
            GST_DEBUG ("    slice %u offset = %u", j, entry->slice_offset[j]);
          }

          for (j = 0; j < segment->pos_table_count; j++) {
            mxf_fraction_parse (&entry->pos_table[j], tag_data, tag_size);
            tag_data += 8;
            tag_size -= 8;
            GST_DEBUG ("    pos table %u = %d/%d", j, entry->pos_table[j].n,
                entry->pos_table[j].d);
          }
        }
        break;
      }
      default:
        if (!mxf_local_tag_add_to_hash_table (primer, tag, tag_data, tag_size,
                &segment->other_tags))
          goto error;
        break;
    }

  next:
    data += 4 + tag_size;
    size -= 4 + tag_size;
  }
  return TRUE;

error:
  GST_ERROR ("Invalid index table segment");
  return FALSE;
}
Esempio n. 19
0
static GstFlowReturn
gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length,
    gint * rread)
{
  GstFlowReturn ret;

  guint8 *buf;

  gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;

  guint64 total;

  guint8 b;

  ret = gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf);
  if (ret != GST_FLOW_OK)
    return ret;

  b = GST_READ_UINT8 (buf);

  total = (guint64) b;

  while (read <= 8 && !(total & len_mask)) {
    read++;
    len_mask >>= 1;
  }
  if (read > 8) {
    guint64 pos = ebml->offset;

    GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
        ("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT
            " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
    return GST_FLOW_ERROR;
  }

  if ((total &= (len_mask - 1)) == len_mask - 1)
    num_ffs++;

  ret = gst_ebml_read_peek_bytes (ebml, read, NULL, &buf);
  if (ret != GST_FLOW_OK)
    return ret;

  while (n < read) {
    guint8 b = GST_READ_UINT8 (buf + n);

    if (b == 0xff)
      num_ffs++;
    total = (total << 8) | b;
    ++n;
  }

  if (read == num_ffs)
    *length = G_MAXUINT64;
  else
    *length = total;

  if (rread)
    *rread = read;

  ebml->offset += read;

  return GST_FLOW_OK;
}
GstBuffer *
mpegtsmux_prepare_h264 (GstBuffer * buf, MpegTsPadData * data, MpegTsMuxEnhanced * mux)
{
  guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
  gsize out_offset = 0, in_offset = 0;
  GstBuffer *out_buf;
  gboolean changed;
  PrivDataH264 *h264_data;
  GstClockTimeDiff diff = GST_CLOCK_TIME_NONE;

  GST_DEBUG_OBJECT (mux, "Preparing H264 buffer for output");

  changed = mpegtsmux_process_codec_data_h264 (data, mux);
  h264_data = (PrivDataH264 *) data->prepare_data;

  if (GST_CLOCK_TIME_IS_VALID (h264_data->last_resync_ts) &&
      GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) {
    diff = GST_CLOCK_DIFF (h264_data->last_resync_ts,
        GST_BUFFER_TIMESTAMP (buf));
  }

  if (changed || (GST_CLOCK_TIME_IS_VALID (diff) && diff > SPS_PPS_PERIOD)) {
    out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2 +
        GST_BUFFER_SIZE (h264_data->cached_es));
    h264_data->last_resync_ts = GST_BUFFER_TIMESTAMP (buf);
    memcpy (GST_BUFFER_DATA (out_buf), GST_BUFFER_DATA (h264_data->cached_es),
        GST_BUFFER_SIZE (h264_data->cached_es));
    out_offset = GST_BUFFER_SIZE (h264_data->cached_es);
    GST_DEBUG_OBJECT (mux, "prepending SPS/PPS information to that packet");
  } else {
    out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2);
  }

  /* We want the same metadata */
  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);

  while (in_offset < GST_BUFFER_SIZE (buf) &&
      out_offset < GST_BUFFER_SIZE (out_buf) - 4) {
    guint32 nal_size = 0;

    switch (h264_data->nal_length_size) {
      case 1:
        nal_size = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + in_offset);
        break;
      case 2:
        nal_size = GST_READ_UINT16_BE (GST_BUFFER_DATA (buf) + in_offset);
        break;
      case 4:
        nal_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + in_offset);
        break;
      default:
        GST_WARNING_OBJECT (mux, "unsupported NAL length size %u",
            h264_data->nal_length_size);
    }
    in_offset += h264_data->nal_length_size;

    /* Generate an Elementary stream buffer by inserting a startcode */
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
    out_offset += 4;
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
        GST_BUFFER_DATA (buf) + in_offset,
        MIN (nal_size, GST_BUFFER_SIZE (out_buf) - out_offset));
    in_offset += nal_size;
    out_offset += nal_size;
  }

  if (out_offset > GST_BUFFER_SIZE (out_buf)) {
    GST_WARNING_OBJECT (mux, "Calculated buffer size %" G_GSIZE_FORMAT
        " is greater than max expected size %u, "
        "using max expected size (Input might not be in "
        "avc format", out_offset, GST_BUFFER_SIZE (out_buf));
    out_offset = GST_BUFFER_SIZE (out_buf);
  }
  GST_BUFFER_SIZE (out_buf) = out_offset;

  return out_buf;
}
static inline gboolean
mpegtsmux_process_codec_data_h264 (MpegTsPadData * data, MpegTsMuxEnhanced * mux)
{
  PrivDataH264 *h264_data;
  gboolean ret = FALSE;

  /* Initialize our private data structure for caching */
  if (G_UNLIKELY (!data->prepare_data)) {
    data->prepare_data = g_new0 (PrivDataH264, 1);
    h264_data = (PrivDataH264 *) data->prepare_data;
    h264_data->last_resync_ts = GST_CLOCK_TIME_NONE;
  }

  h264_data = (PrivDataH264 *) data->prepare_data;

  /* Detect a codec data change */
  if (h264_data->last_codec_data != data->codec_data) {
    if (h264_data->cached_es) {
      gst_buffer_unref (h264_data->cached_es);
      h264_data->cached_es = NULL;
    }
    ret = TRUE;
  }

  /* Generate the SPS/PPS ES header that will be prepended regularly */
  if (G_UNLIKELY (!h264_data->cached_es)) {
    gint offset = 4, i = 0, nb_sps = 0, nb_pps = 0;
    gsize out_offset = 0;
    guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
    h264_data->last_codec_data = data->codec_data;
    h264_data->cached_es =
        gst_buffer_new_and_alloc (GST_BUFFER_SIZE (data->codec_data) * 10);

    /* Get NAL length size */
    h264_data->nal_length_size =
        (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x03) +
        1;
    GST_LOG_OBJECT (mux, "NAL length will be coded on %u bytes",
        h264_data->nal_length_size);
    offset++;

    /* How many SPS */
    nb_sps =
        GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x1f;
    GST_DEBUG_OBJECT (mux, "we have %d Sequence Parameter Set", nb_sps);
    offset++;

    /* For each SPS */
    for (i = 0; i < nb_sps; i++) {
      guint16 sps_size =
          GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset);

      GST_LOG_OBJECT (mux, "Sequence Parameter Set is %d bytes", sps_size);

      /* Jump over SPS size */
      offset += 2;

      /* Fake a start code */
      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
          startcode, 4);
      out_offset += 4;
      /* Now push the SPS */
      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
          GST_BUFFER_DATA (data->codec_data) + offset, sps_size);

      out_offset += sps_size;
      offset += sps_size;
    }

    /* How many PPS */
    nb_pps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset);
    GST_LOG_OBJECT (mux, "we have %d Picture Parameter Set", nb_sps);
    offset++;

    /* For each PPS */
    for (i = 0; i < nb_pps; i++) {
      gint pps_size =
          GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset);

      GST_LOG_OBJECT (mux, "Picture Parameter Set is %d bytes", pps_size);

      /* Jump over PPS size */
      offset += 2;

      /* Fake a start code */
      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
          startcode, 4);
      out_offset += 4;
      /* Now push the PPS */
      memcpy (GST_BUFFER_DATA (h264_data->cached_es) + out_offset,
          GST_BUFFER_DATA (data->codec_data) + offset, pps_size);

      out_offset += pps_size;
      offset += pps_size;
    }
    GST_BUFFER_SIZE (h264_data->cached_es) = out_offset;
    GST_DEBUG_OBJECT (mux, "generated a %" G_GSIZE_FORMAT
        " bytes SPS/PPS header", out_offset);
  }
  return ret;
}
static gpointer
_parse_atsc_mgt (GstMpegtsSection * section)
{
    GstMpegtsAtscMGT *mgt = NULL;
    guint i = 0;
    guint8 *data, *end;
    guint16 descriptors_loop_length;

    mgt = g_slice_new0 (GstMpegtsAtscMGT);

    data = section->data;
    end = data + section->section_length;

    /* Skip already parsed data */
    data += 8;

    mgt->protocol_version = GST_READ_UINT8 (data);
    data += 1;
    mgt->tables_defined = GST_READ_UINT16_BE (data);
    data += 2;
    mgt->tables = g_ptr_array_new_full (mgt->tables_defined,
                                        (GDestroyNotify) _gst_mpegts_atsc_mgt_table_free);
    for (i = 0; i < mgt->tables_defined && data + 11 < end; i++) {
        GstMpegtsAtscMGTTable *mgt_table;

        if (data + 11 >= end) {
            GST_WARNING ("MGT data too short to parse inner table num %d", i);
            goto error;
        }

        mgt_table = g_slice_new0 (GstMpegtsAtscMGTTable);
        g_ptr_array_add (mgt->tables, mgt_table);

        mgt_table->table_type = GST_READ_UINT16_BE (data);
        data += 2;
        mgt_table->pid = GST_READ_UINT16_BE (data) & 0x1FFF;
        data += 2;
        mgt_table->version_number = GST_READ_UINT8 (data) & 0x1F;
        data += 1;
        mgt_table->number_bytes = GST_READ_UINT32_BE (data);
        data += 4;
        descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
        data += 2;

        if (data + descriptors_loop_length >= end) {
            GST_WARNING ("MGT data too short to parse inner table descriptors (table "
                         "num %d", i);
            goto error;
        }
        mgt_table->descriptors =
            gst_mpegts_parse_descriptors (data, descriptors_loop_length);
        data += descriptors_loop_length;
    }

    descriptors_loop_length = GST_READ_UINT16_BE (data) & 0xFFF;
    data += 2;
    if (data + descriptors_loop_length >= end) {
        GST_WARNING ("MGT data too short to parse descriptors");
        goto error;
    }
    mgt->descriptors =
        gst_mpegts_parse_descriptors (data, descriptors_loop_length);
    data += descriptors_loop_length;

    return (gpointer) mgt;

error:
    _gst_mpegts_atsc_mgt_free (mgt);

    return NULL;
}
static GPtrArray *
_parse_atsc_mult_string (guint8 * data, guint datasize)
{
    guint8 num_strings;
    GPtrArray *res = NULL;
    guint8 *end = data + datasize;
    gint i;

    if (datasize > 0) {
        /* 1 is the minimum entry size, so no need to check here */
        num_strings = GST_READ_UINT8 (data);
        data += 1;

        res =
            g_ptr_array_new_full (num_strings,
                                  (GDestroyNotify) _gst_mpegts_atsc_mult_string_free);

        for (i = 0; i < num_strings; i++) {
            GstMpegtsAtscMultString *mstring;
            guint8 num_segments;
            gint j;

            mstring = g_slice_new0 (GstMpegtsAtscMultString);
            g_ptr_array_add (res, mstring);
            mstring->segments =
                g_ptr_array_new_full (num_strings,
                                      (GDestroyNotify) _gst_mpegts_atsc_string_segment_free);

            /* each entry needs at least 4 bytes (lang code and segments number) */
            if (end - data < 4) {
                GST_WARNING ("Data too short for multstring parsing %d",
                             (gint) (end - data));
                goto error;
            }

            mstring->iso_639_langcode[0] = GST_READ_UINT8 (data);
            data += 1;
            mstring->iso_639_langcode[1] = GST_READ_UINT8 (data);
            data += 1;
            mstring->iso_639_langcode[2] = GST_READ_UINT8 (data);
            data += 1;
            num_segments = GST_READ_UINT8 (data);
            data += 1;

            for (j = 0; j < num_segments; j++) {
                GstMpegtsAtscStringSegment *seg;

                seg = g_slice_new0 (GstMpegtsAtscStringSegment);
                g_ptr_array_add (mstring->segments, seg);

                /* each entry needs at least 3 bytes */
                if (end - data < 3) {
                    GST_WARNING ("Data too short for multstring parsing %d", datasize);
                    goto error;
                }

                seg->compression_type = GST_READ_UINT8 (data);
                data += 1;
                seg->mode = GST_READ_UINT8 (data);
                data += 1;
                seg->compressed_data_size = GST_READ_UINT8 (data);
                data += 1;

                if (end - data < seg->compressed_data_size) {
                    GST_WARNING ("Data too short for multstring parsing %d", datasize);
                    goto error;
                }

                if (seg->compressed_data_size)
                    seg->compressed_data = data;
                data += seg->compressed_data_size;
            }

        }
    }
    return res;

error:
    if (res)
        g_ptr_array_unref (res);
    return NULL;
}
Esempio n. 24
0
GstBuffer *
mpegpsmux_prepare_h264 (GstBuffer * buf, MpegPsPadData * data, MpegPsMux * mux)
{
  guint8 nal_length_size = 0;
  guint8 startcode[4] = { 0x00, 0x00, 0x00, 0x01 };
  GstBuffer *out_buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) * 2);
  gint offset = 4, i = 0, nb_sps = 0, nb_pps = 0;
  gsize out_offset = 0, in_offset = 0;

  GST_DEBUG_OBJECT (mux, "Preparing H264 buffer for output");

  /* We want the same metadata */
  gst_buffer_copy_metadata (out_buf, buf, GST_BUFFER_COPY_ALL);

  /* Get NAL length size */
  nal_length_size =
      (GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x03) + 1;
  GST_LOG_OBJECT (mux, "NAL length will be coded on %u bytes", nal_length_size);
  offset++;

  /* Generate SPS */
  nb_sps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset) & 0x1f;
  GST_DEBUG_OBJECT (mux, "we have %d Sequence Parameter Set", nb_sps);
  offset++;

  /* For each SPS */
  for (i = 0; i < nb_sps; i++) {
    guint16 sps_size =
        GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset);

    GST_LOG_OBJECT (mux, "Sequence Parameter Set is %d bytes", sps_size);

    /* Jump over SPS size */
    offset += 2;

    /* Fake a start code */
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
    out_offset += 4;
    /* Now push the SPS */
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
        GST_BUFFER_DATA (data->codec_data) + offset, sps_size);

    out_offset += sps_size;
    offset += sps_size;
  }

  nb_pps = GST_READ_UINT8 (GST_BUFFER_DATA (data->codec_data) + offset);
  GST_LOG_OBJECT (mux, "we have %d Picture Parameter Set", nb_sps);
  offset++;

  /* For each PPS */
  for (i = 0; i < nb_pps; i++) {
    gint pps_size =
        GST_READ_UINT16_BE (GST_BUFFER_DATA (data->codec_data) + offset);

    GST_LOG_OBJECT (mux, "Picture Parameter Set is %d bytes", pps_size);

    /* Jump over PPS size */
    offset += 2;

    /* Fake a start code */
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
    out_offset += 4;
    /* Now push the PPS */
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
        GST_BUFFER_DATA (data->codec_data) + offset, pps_size);

    out_offset += pps_size;
    offset += pps_size;
  }

  while (in_offset < GST_BUFFER_SIZE (buf) &&
      out_offset < GST_BUFFER_SIZE (out_buf) - 4) {
    guint32 nal_size = 0;

    switch (nal_length_size) {
      case 1:
        nal_size = GST_READ_UINT8 (GST_BUFFER_DATA (buf) + in_offset);
        break;
      case 2:
        nal_size = GST_READ_UINT16_BE (GST_BUFFER_DATA (buf) + in_offset);
        break;
      case 4:
        nal_size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + in_offset);
        break;
      default:
        GST_WARNING_OBJECT (mux, "unsupported NAL length size %u",
            nal_length_size);
    }
    in_offset += nal_length_size;

    /* Generate an Elementary stream buffer by inserting a startcode */
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset, startcode, 4);
    out_offset += 4;
    memcpy (GST_BUFFER_DATA (out_buf) + out_offset,
        GST_BUFFER_DATA (buf) + in_offset,
        MIN (nal_size, GST_BUFFER_SIZE (out_buf) - out_offset));
    in_offset += nal_size;
    out_offset += nal_size;
  }

  GST_BUFFER_SIZE (out_buf) = out_offset;

  return out_buf;
}
static gpointer
_parse_atsc_eit (GstMpegtsSection * section)
{
    GstMpegtsAtscEIT *eit = NULL;
    guint i = 0;
    guint8 *data, *end;
    guint8 num_events;

    eit = g_slice_new0 (GstMpegtsAtscEIT);

    data = section->data;
    end = data + section->section_length;

    eit->source_id = section->subtable_extension;

    /* Skip already parsed data */
    data += 8;

    eit->protocol_version = GST_READ_UINT8 (data);
    data += 1;
    num_events = GST_READ_UINT8 (data);
    data += 1;

    eit->events = g_ptr_array_new_with_free_func ((GDestroyNotify)
                  _gst_mpegts_atsc_eit_event_free);

    for (i = 0; i < num_events; i++) {
        GstMpegtsAtscEITEvent *event;
        guint32 tmp;
        guint8 text_length;
        guint16 descriptors_loop_length;

        if (end - data < 12) {
            GST_WARNING ("PID %d invalid EIT entry length %d with %u events",
                         section->pid, (gint) (end - 4 - data), num_events);
            goto error;
        }

        event = g_slice_new0 (GstMpegtsAtscEITEvent);
        g_ptr_array_add (eit->events, event);

        event->event_id = GST_READ_UINT16_BE (data) & 0x3FFF;
        data += 2;
        event->start_time = GST_READ_UINT32_BE (data);
        data += 4;

        tmp = GST_READ_UINT32_BE (data);
        data += 4;
        event->etm_location = (tmp >> 28) & 0x3;
        event->length_in_seconds = (tmp >> 8) & 0x0FFFFF;
        text_length = tmp & 0xFF;

        if (text_length > end - data - 4 - 2) {
            GST_WARNING ("PID %d invalid EIT entry length %d with %u events",
                         section->pid, (gint) (end - 4 - data), num_events);
            goto error;
        }
        event->titles = _parse_atsc_mult_string (data, text_length);
        data += text_length;

        descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
        data += 2;

        if (end - data - 4 < descriptors_loop_length) {
            GST_WARNING ("PID %d invalid EIT entry length %d with %u events",
                         section->pid, (gint) (end - 4 - data), num_events);
            goto error;
        }

        event->descriptors =
            gst_mpegts_parse_descriptors (data, descriptors_loop_length);
        data += descriptors_loop_length;
    }

    if (data != end - 4) {
        GST_WARNING ("PID %d invalid EIT parsed %d length %d",
                     section->pid, (gint) (data - section->data), section->section_length);
        goto error;
    }

    return (gpointer) eit;

error:
    _gst_mpegts_atsc_eit_free (eit);

    return NULL;

}