Exemple #1
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;
}
static GstFlowReturn
gst_nuv_demux_extended_header_load (GstNuvDemux * nuv,
    nuv_extended_header ** h_ret)
{
  unsigned char *data;
  GstBuffer *buff = NULL;
  nuv_extended_header *h;


  GstFlowReturn res = gst_nuv_demux_read_bytes (nuv, 512, TRUE, &buff);

  if (res != GST_FLOW_OK) {
    if (buff != NULL) {
      gst_buffer_unref (buff);
    }
    return res;
  }

  h = g_new0 (nuv_extended_header, 1);
  data = buff->data;
  h->i_version = GST_READ_UINT32_LE (&data[0]);
  h->i_video_fcc = GST_MAKE_FOURCC (data[4], data[5], data[6], data[7]);
  h->i_audio_fcc = GST_MAKE_FOURCC (data[8], data[9], data[10], data[11]);
  h->i_audio_sample_rate = GST_READ_UINT32_LE (&data[12]);
  h->i_audio_bits_per_sample = GST_READ_UINT32_LE (&data[16]);
  h->i_audio_channels = GST_READ_UINT32_LE (&data[20]);
  h->i_audio_compression_ratio = GST_READ_UINT32_LE (&data[24]);
  h->i_audio_quality = GST_READ_UINT32_LE (&data[28]);
  h->i_rtjpeg_quality = GST_READ_UINT32_LE (&data[32]);
  h->i_rtjpeg_luma_filter = GST_READ_UINT32_LE (&data[36]);
  h->i_rtjpeg_chroma_filter = GST_READ_UINT32_LE (&data[40]);
  h->i_lavc_bitrate = GST_READ_UINT32_LE (&data[44]);
  h->i_lavc_qmin = GST_READ_UINT32_LE (&data[48]);
  h->i_lavc_qmin = GST_READ_UINT32_LE (&data[52]);
  h->i_lavc_maxqdiff = GST_READ_UINT32_LE (&data[56]);
  h->i_seekable_offset = GST_READ_UINT64_LE (&data[60]);
  h->i_keyframe_adjust_offset = GST_READ_UINT64_LE (&data[68]);

  GST_DEBUG_OBJECT (nuv,
      "ex hdr: v=%d vffc=%4.4s afcc=%4.4s %dHz %dbits ach=%d acr=%d aq=%d"
      "rtjpeg q=%d lf=%d lc=%d lavc br=%d qmin=%d qmax=%d maxqdiff=%d seekableoff=%lld keyfao=%lld",
      h->i_version, (gchar *) & h->i_video_fcc, (gchar *) & h->i_audio_fcc,
      h->i_audio_sample_rate, h->i_audio_bits_per_sample, h->i_audio_channels,
      h->i_audio_compression_ratio, h->i_audio_quality, h->i_rtjpeg_quality,
      h->i_rtjpeg_luma_filter, h->i_rtjpeg_chroma_filter, h->i_lavc_bitrate,
      h->i_lavc_qmin, h->i_lavc_qmax, h->i_lavc_maxqdiff, h->i_seekable_offset,
      h->i_keyframe_adjust_offset);

  *h_ret = h;
  gst_buffer_unref (buff);
  return res;
}
/**
 * gst_audio_format_fill_silence:
 * @info: a #GstAudioFormatInfo
 * @dest: (array length=length) (element-type guint8): a destination
 *   to fill
 * @length: the length to fill
 *
 * Fill @length bytes in @dest with silence samples for @info.
 */
void
gst_audio_format_fill_silence (const GstAudioFormatInfo * info,
    gpointer dest, gsize length)
{
  guint8 *dptr = dest;

  g_return_if_fail (info != NULL);
  g_return_if_fail (dest != NULL);

  if (info->flags & GST_AUDIO_FORMAT_FLAG_FLOAT ||
      info->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) {
    /* float or signed always 0 */
    orc_memset (dest, 0, length);
  } else {
    gint i, j, bps = info->width >> 3;

    switch (bps) {
      case 1:
        orc_memset (dest, info->silence[0], length);
        break;
      case 2:{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
        guint16 silence = GST_READ_UINT16_LE (info->silence);
#else
        guint16 silence = GST_READ_UINT16_BE (info->silence);
#endif
        audio_orc_splat_u16 (dest, silence, length / bps);
        break;
      }
      case 4:{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
        guint32 silence = GST_READ_UINT32_LE (info->silence);
#else
        guint32 silence = GST_READ_UINT32_BE (info->silence);
#endif
        audio_orc_splat_u32 (dest, silence, length / bps);
        break;
      }
      case 8:{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
        guint64 silence = GST_READ_UINT64_LE (info->silence);
#else
        guint64 silence = GST_READ_UINT64_BE (info->silence);
#endif
        audio_orc_splat_u64 (dest, silence, length / bps);
        break;
      }
      default:
        for (i = 0; i < length; i += bps) {
          for (j = 0; j < bps; j++)
            *dptr++ = info->silence[j];
        }
        break;
    }
  }
}
Exemple #4
0
static GstFlowReturn
gst_ivf_parse_handle_frame_data (GstIvfParse * ivf, GstBaseParseFrame * frame,
    gint * skipsize)
{
  GstBuffer *const buffer = frame->buffer;
  GstMapInfo map;
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *out_buffer;

  gst_buffer_map (buffer, &map, GST_MAP_READ);
  if (map.size >= IVF_FILE_HEADER_SIZE) {
    guint32 frame_size = GST_READ_UINT32_LE (map.data);
    guint64 frame_pts = GST_READ_UINT64_LE (map.data + 4);

    GST_LOG_OBJECT (ivf,
        "Read frame header: size %u, pts %" G_GUINT64_FORMAT, frame_size,
        frame_pts);

    if (map.size < IVF_FRAME_HEADER_SIZE + frame_size) {
      gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (ivf),
          IVF_FRAME_HEADER_SIZE + frame_size);
      gst_buffer_unmap (buffer, &map);
      *skipsize = 0;
      goto end;
    }

    gst_buffer_unmap (buffer, &map);

    /* Eventually, we would need the buffer memory in a merged state anyway */
    out_buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_FLAGS |
        GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_META |
        GST_BUFFER_COPY_MEMORY | GST_BUFFER_COPY_MERGE,
        IVF_FRAME_HEADER_SIZE, frame_size);
    if (!out_buffer) {
      GST_ERROR_OBJECT (ivf, "Failed to copy frame buffer");
      ret = GST_FLOW_ERROR;
      *skipsize = IVF_FRAME_HEADER_SIZE + frame_size;
      goto end;
    }
    gst_buffer_replace (&frame->out_buffer, out_buffer);
    gst_buffer_unref (out_buffer);

    /* Detect resolution changes on key frames */
    if (gst_buffer_map (frame->out_buffer, &map, GST_MAP_READ)) {
      guint32 width, height;

      if (ivf->fourcc == GST_MAKE_FOURCC ('V', 'P', '8', '0')) {
        guint32 frame_tag;
        frame_tag = GST_READ_UINT24_LE (map.data);
        if (!(frame_tag & 0x01) && map.size >= 10) {    /* key frame */
          GST_DEBUG_OBJECT (ivf, "key frame detected");

          width = GST_READ_UINT16_LE (map.data + 6) & 0x3fff;
          height = GST_READ_UINT16_LE (map.data + 8) & 0x3fff;
          gst_ivf_parse_set_size (ivf, width, height);
        }
      } else if (ivf->fourcc == GST_MAKE_FOURCC ('V', 'P', '9', '0')) {
        /* Fixme: Add vp9 frame header parsing? */
      } else if (ivf->fourcc == GST_MAKE_FOURCC ('A', 'V', '0', '1')) {
        /* Fixme: Add av1 frame header parsing? */
        /* This would allow to parse dynamic resolution changes */
        /* implement when gstav1parser is ready */
      }
      gst_buffer_unmap (frame->out_buffer, &map);
    }

    if (ivf->fps_n > 0) {
      GST_BUFFER_TIMESTAMP (out_buffer) =
          gst_util_uint64_scale_int (GST_SECOND * frame_pts, ivf->fps_d,
          ivf->fps_n);
    }

    gst_ivf_parse_update_src_caps (ivf);

    ret = gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (ivf), frame,
        IVF_FRAME_HEADER_SIZE + frame_size);
    *skipsize = 0;
  } else {
    GST_LOG_OBJECT (ivf, "Frame data not yet available.");
    gst_buffer_unmap (buffer, &map);
    *skipsize = 0;
  }

end:
  return ret;
}
/* chain function
 * this function does the actual processing
 */
static GstFlowReturn
gst_ivf_parse_chain (GstPad * pad, GstBuffer * buf)
{
  GstIvfParse *ivf = GST_IVF_PARSE (GST_OBJECT_PARENT (pad));
  gboolean res;

  /* lazy creation of the adapter */
  if (G_UNLIKELY (ivf->adapter == NULL)) {
    ivf->adapter = gst_adapter_new ();
  }

  GST_LOG_OBJECT (ivf, "Pushing buffer of size %u to adapter",
      GST_BUFFER_SIZE (buf));

  gst_adapter_push (ivf->adapter, buf); /* adapter takes ownership of buf */

  res = GST_FLOW_OK;

  switch (ivf->state) {
    case GST_IVF_PARSE_START:
      if (gst_adapter_available (ivf->adapter) >= 32) {
        GstCaps *caps;

        const guint8 *data = gst_adapter_peek (ivf->adapter, 32);
        guint32 magic = GST_READ_UINT32_LE (data);
        guint16 version = GST_READ_UINT16_LE (data + 4);
        guint16 header_size = GST_READ_UINT16_LE (data + 6);
        guint32 fourcc = GST_READ_UINT32_LE (data + 8);
        guint16 width = GST_READ_UINT16_LE (data + 12);
        guint16 height = GST_READ_UINT16_LE (data + 14);
        guint32 rate_num = GST_READ_UINT32_LE (data + 16);
        guint32 rate_den = GST_READ_UINT32_LE (data + 20);
#ifndef GST_DISABLE_GST_DEBUG
        guint32 num_frames = GST_READ_UINT32_LE (data + 24);
#endif

        /* last 4 bytes unused */
        gst_adapter_flush (ivf->adapter, 32);

        if (magic != GST_MAKE_FOURCC ('D', 'K', 'I', 'F') ||
            version != 0 || header_size != 32 ||
            fourcc != GST_MAKE_FOURCC ('V', 'P', '8', '0')) {
          GST_ELEMENT_ERROR (ivf, STREAM, WRONG_TYPE, (NULL), (NULL));
          return GST_FLOW_ERROR;
        }

        /* create src pad caps */
        caps = gst_caps_new_simple ("video/x-vp8",
            "width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
            "framerate", GST_TYPE_FRACTION, rate_num, rate_den, NULL);

        GST_INFO_OBJECT (ivf, "Found stream: %" GST_PTR_FORMAT, caps);

        GST_LOG_OBJECT (ivf, "Stream has %d frames", num_frames);

        gst_pad_set_caps (ivf->srcpad, caps);
        gst_caps_unref (caps);

        /* keep framerate in instance for convenience */
        ivf->rate_num = rate_num;
        ivf->rate_den = rate_den;

        gst_pad_push_event (ivf->srcpad, gst_event_new_new_segment (FALSE, 1.0,
                GST_FORMAT_TIME, 0, -1, 0));

        /* move along */
        ivf->state = GST_IVF_PARSE_DATA;
      } else {
        GST_LOG_OBJECT (ivf, "Header data not yet available.");
        break;
      }

      /* fall through */

    case GST_IVF_PARSE_DATA:
      while (gst_adapter_available (ivf->adapter) > 12) {
        const guint8 *data = gst_adapter_peek (ivf->adapter, 12);
        guint32 frame_size = GST_READ_UINT32_LE (data);
        guint64 frame_pts = GST_READ_UINT64_LE (data + 4);

        GST_LOG_OBJECT (ivf,
            "Read frame header: size %u, pts %" G_GUINT64_FORMAT, frame_size,
            frame_pts);

        if (gst_adapter_available (ivf->adapter) >= 12 + frame_size) {
          GstBuffer *frame;

          gst_adapter_flush (ivf->adapter, 12);

          frame = gst_adapter_take_buffer (ivf->adapter, frame_size);
          gst_buffer_set_caps (frame, GST_PAD_CAPS (ivf->srcpad));
          GST_BUFFER_TIMESTAMP (frame) =
              gst_util_uint64_scale_int (GST_SECOND * frame_pts, ivf->rate_den,
              ivf->rate_num);
          GST_BUFFER_DURATION (frame) =
              gst_util_uint64_scale_int (GST_SECOND, ivf->rate_den,
              ivf->rate_num);

          GST_DEBUG_OBJECT (ivf, "Pushing frame of size %u, ts %"
              GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ", off %"
              G_GUINT64_FORMAT ", off_end %" G_GUINT64_FORMAT,
              GST_BUFFER_SIZE (frame),
              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (frame)),
              GST_TIME_ARGS (GST_BUFFER_DURATION (frame)),
              GST_BUFFER_OFFSET (frame), GST_BUFFER_OFFSET_END (frame));

          res = gst_pad_push (ivf->srcpad, frame);
          if (res != GST_FLOW_OK)
            break;
        } else {
          GST_LOG_OBJECT (ivf, "Frame data not yet available.");
          break;
        }
      }
      break;

    default:
      g_return_val_if_reached (GST_FLOW_ERROR);
  }

  return res;
}