/* for off == 0 initial code; returns TRUE if code starts a frame,
 * otherwise returns TRUE if code terminates preceding frame */
static gboolean
gst_mpegv_parse_process_sc (GstMpegvParse * mpvparse, GstBuffer * buf, gint off)
{
  gboolean ret = FALSE, do_seq = TRUE;
  guint8 *data;
  guint code;

  g_return_val_if_fail (buf && GST_BUFFER_SIZE (buf) >= 4, FALSE);

  data = GST_BUFFER_DATA (buf);
  code = data[off + 3];

  GST_LOG_OBJECT (mpvparse, "process startcode %x (%s)", code,
      picture_start_code_name (code));

  switch (code) {
    case MPEG_PACKET_PICTURE:
      GST_LOG_OBJECT (mpvparse, "startcode is PICTURE");
      /* picture is aggregated with preceding sequence/gop, if any.
       * so, picture start code only ends if already a previous one */
      if (mpvparse->pic_offset < 0)
        mpvparse->pic_offset = off;
      else
        ret = TRUE;
      if (!off)
        ret = TRUE;
      break;
    case MPEG_PACKET_SEQUENCE:
      GST_LOG_OBJECT (mpvparse, "startcode is SEQUENCE");
      if (off == 0)
        mpvparse->seq_offset = off;
      ret = TRUE;
      break;
    case MPEG_PACKET_GOP:
      GST_LOG_OBJECT (mpvparse, "startcode is GOP");
      if (mpvparse->seq_offset >= 0)
        ret = mpvparse->gop_split;
      else
        ret = TRUE;
      break;
    default:
      do_seq = FALSE;
      break;
  }

  /* process config data */
  if (G_UNLIKELY (mpvparse->seq_offset >= 0 && off && do_seq)) {
    g_assert (mpvparse->seq_offset == 0);
    gst_mpegv_parse_process_config (mpvparse, GST_BUFFER_DATA (buf), off);
    /* avoid accepting again for a PICTURE sc following a GOP sc */
    mpvparse->seq_offset = -1;
  }

  /* extract some picture info if there is any in the frame being terminated */
  if (G_UNLIKELY (ret && off)) {
    if (G_LIKELY (mpvparse->pic_offset >= 0 && mpvparse->pic_offset < off)) {
      if (G_LIKELY (GST_BUFFER_SIZE (buf) >= mpvparse->pic_offset + 6)) {
        gint pct = (data[mpvparse->pic_offset + 5] >> 3) & 0x7;

        GST_LOG_OBJECT (mpvparse, "picture_coding_type %d (%s)", pct,
            picture_type_name (pct));
        mpvparse->intra_frame = (pct == MPEG_PICTURE_TYPE_I);
      } else {
        GST_WARNING_OBJECT (mpvparse, "no data following PICTURE startcode");
        mpvparse->intra_frame = FALSE;
      }
    } else {
/* for off == 4 initial code; returns TRUE if code starts a frame
 * otherwise returns TRUE if code terminates preceding frame */
static gboolean
gst_mpegv_parse_process_sc (GstMpegvParse * mpvparse,
    GstBuffer * buf, gint off, guint8 code)
{
  gboolean ret = FALSE, packet = TRUE;

  g_return_val_if_fail (buf && gst_buffer_get_size (buf) >= 4, FALSE);

  GST_LOG_OBJECT (mpvparse, "process startcode %x (%s)", code,
      picture_start_code_name (code));

  switch (code) {
    case GST_MPEG_VIDEO_PACKET_PICTURE:
      GST_LOG_OBJECT (mpvparse, "startcode is PICTURE");
      /* picture is aggregated with preceding sequence/gop, if any.
       * so, picture start code only ends if already a previous one */
      if (mpvparse->pic_offset < 0)
        mpvparse->pic_offset = off;
      else
        ret = (off != mpvparse->pic_offset);
      /* but it's a valid starting one */
      if (off == 4)
        ret = TRUE;
      break;
    case GST_MPEG_VIDEO_PACKET_SEQUENCE:
      GST_LOG_OBJECT (mpvparse, "startcode is SEQUENCE");
      if (mpvparse->seq_offset < 0)
        mpvparse->seq_offset = off;
      ret = TRUE;
      break;
    case GST_MPEG_VIDEO_PACKET_GOP:
      GST_LOG_OBJECT (mpvparse, "startcode is GOP");
      if (mpvparse->seq_offset >= 0)
        ret = mpvparse->gop_split;
      else
        ret = TRUE;
      break;
    case GST_MPEG_VIDEO_PACKET_EXTENSION:
      GST_LOG_OBJECT (mpvparse, "startcode is VIDEO PACKET EXTENSION");
      parse_picture_extension (mpvparse, buf, off);
      if (mpvparse->ext_count < G_N_ELEMENTS (mpvparse->ext_offsets))
        mpvparse->ext_offsets[mpvparse->ext_count++] = off;
      /* fall-through */
    default:
      packet = FALSE;
      break;
  }

  /* set size to avoid processing config again */
  if (mpvparse->seq_offset >= 0 && off != mpvparse->seq_offset &&
      !mpvparse->seq_size && packet) {
    /* should always be at start */
    g_assert (mpvparse->seq_offset <= 4);
    gst_mpegv_parse_process_config (mpvparse, buf, off - mpvparse->seq_offset);
    mpvparse->seq_size = off - mpvparse->seq_offset;
  }

  /* extract some picture info if there is any in the frame being terminated */
  if (ret && mpvparse->pic_offset >= 0 && mpvparse->pic_offset < off) {
    GstMapInfo map;

    gst_buffer_map (buf, &map, GST_MAP_READ);
    if (gst_mpeg_video_parse_picture_header (&mpvparse->pichdr,
            map.data, map.size, mpvparse->pic_offset))
      GST_LOG_OBJECT (mpvparse, "picture_coding_type %d (%s), ending"
          "frame of size %d", mpvparse->pichdr.pic_type,
          picture_type_name (mpvparse->pichdr.pic_type), off - 4);
    else
      GST_LOG_OBJECT (mpvparse, "Couldn't parse picture at offset %d",
          mpvparse->pic_offset);

    gst_buffer_unmap (buf, &map);
  }

  return ret;
}
Beispiel #3
0
/* for off == 4 initial code; returns TRUE if code starts a frame
 * otherwise returns TRUE if code terminates preceding frame */
static gboolean
gst_mpegv_parse_process_sc (GstMpegvParse * mpvparse,
    GstMapInfo * info, gint off, GstMpegVideoPacket * packet)
{
  gboolean ret = FALSE, checkconfig = TRUE;

  GST_LOG_OBJECT (mpvparse, "process startcode %x (%s) offset:%d", packet->type,
      picture_start_code_name (packet->type), off);

  switch (packet->type) {
    case GST_MPEG_VIDEO_PACKET_PICTURE:
      GST_LOG_OBJECT (mpvparse, "startcode is PICTURE");
      /* picture is aggregated with preceding sequence/gop, if any.
       * so, picture start code only ends if already a previous one */
      if (mpvparse->pic_offset < 0)
        mpvparse->pic_offset = off;
      else
        ret = (off != mpvparse->pic_offset);
      /* but it's a valid starting one */
      if (off == 4)
        ret = TRUE;
      break;
    case GST_MPEG_VIDEO_PACKET_SEQUENCE:
      GST_LOG_OBJECT (mpvparse, "startcode is SEQUENCE");
      if (mpvparse->seq_offset < 0)
        mpvparse->seq_offset = off;
      ret = TRUE;
      break;
    case GST_MPEG_VIDEO_PACKET_GOP:
      GST_LOG_OBJECT (mpvparse, "startcode is GOP");
      if (mpvparse->seq_offset >= 0)
        ret = mpvparse->gop_split;
      else
        ret = TRUE;
      break;
    case GST_MPEG_VIDEO_PACKET_EXTENSION:
      GST_LOG_OBJECT (mpvparse, "startcode is VIDEO PACKET EXTENSION");
      parse_packet_extension (mpvparse, info, off);
      if (mpvparse->ext_count < G_N_ELEMENTS (mpvparse->ext_offsets))
        mpvparse->ext_offsets[mpvparse->ext_count++] = off;
      checkconfig = FALSE;
      break;
    default:
      if (GST_MPEG_VIDEO_PACKET_IS_SLICE (packet->type)) {
        mpvparse->slice_count++;
        if (mpvparse->slice_offset == 0)
          mpvparse->slice_offset = off - 4;
      }
      checkconfig = FALSE;
      break;
  }

  /* set size to avoid processing config again */
  if (checkconfig && mpvparse->seq_offset >= 0 && off != mpvparse->seq_offset &&
      !mpvparse->seq_size) {
    /* should always be at start */
    g_assert (mpvparse->seq_offset <= 4);
    gst_mpegv_parse_process_config (mpvparse, info, off - mpvparse->seq_offset);
    mpvparse->seq_size = off - mpvparse->seq_offset;
  }

  /* extract some picture info if there is any in the frame being terminated */
  if (ret && mpvparse->pic_offset >= 0 && mpvparse->pic_offset < off) {
    GstMpegVideoPacket header;

    header.data = info->data;
    header.type = GST_MPEG_VIDEO_PACKET_PICTURE;
    header.offset = mpvparse->pic_offset;
    header.size = info->size - mpvparse->pic_offset;
    if (gst_mpeg_video_packet_parse_picture_header (&header, &mpvparse->pichdr))
      GST_LOG_OBJECT (mpvparse, "picture_coding_type %d (%s), ending"
          "frame of size %d", mpvparse->pichdr.pic_type,
          picture_type_name (mpvparse->pichdr.pic_type), off - 4);
    else
      GST_LOG_OBJECT (mpvparse, "Couldn't parse picture at offset %d",
          mpvparse->pic_offset);
  }

  return ret;
}