Example #1
0
static GstFlowReturn
gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer)
{
    GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad));
    GstVdpMpegPacketizer packetizer;
    GstBuffer *buf;
    GstFlowReturn ret = GST_FLOW_OK;

    if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
        GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer");
        gst_vdp_mpeg_dec_flush (mpeg_dec);
    }


    gst_vdp_mpeg_packetizer_init (&packetizer, buffer);
    while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) {
        GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf);
        guint32 sync_code;
        guint8 start_code;

        /* skip sync_code */
        gst_bit_reader_get_bits_uint32 (&b_reader, &sync_code, 8 * 3);

        /* start_code */
        gst_bit_reader_get_bits_uint8 (&b_reader, &start_code, 8);

        if (start_code >= MPEG_PACKET_SLICE_MIN
                && start_code <= MPEG_PACKET_SLICE_MAX) {
            GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE");

            gst_buffer_ref (buf);
            gst_adapter_push (mpeg_dec->adapter, buf);
            mpeg_dec->vdp_info.slice_count++;
        }

        switch (start_code) {
        case MPEG_PACKET_PICTURE:
            GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE");

            if (!gst_vdp_mpeg_dec_parse_picture (mpeg_dec, buf))
                goto done;

            break;
        case MPEG_PACKET_SEQUENCE:
            GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE");
            gst_vdp_mpeg_dec_parse_sequence (mpeg_dec, buf);
            break;
        case MPEG_PACKET_EXTENSION:
        {
            guint8 ext_code;

            GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION");

            /* ext_code */
            gst_bit_reader_get_bits_uint8 (&b_reader, &ext_code, 4);
            switch (ext_code) {
            case MPEG_PACKET_EXT_PICTURE_CODING:
                GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING");
                gst_vdp_mpeg_dec_parse_picture_coding (mpeg_dec, buf);
                break;
            case MPEG_PACKET_EXT_QUANT_MATRIX:
                GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX");
                gst_vdp_mpeg_dec_parse_quant_matrix (mpeg_dec, buf);
                break;
            default:
                break;
            }
            break;
        }
        case MPEG_PACKET_GOP:
            GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP");
            gst_vdp_mpeg_dec_parse_gop (mpeg_dec, buf);
            break;
        default:
            break;
        }

        gst_buffer_unref (buf);
    }

    if (mpeg_dec->state == GST_VDP_MPEG_DEC_NEED_SEQUENCE ||
            mpeg_dec->state == GST_VDP_MPEG_DEC_NEED_GOP) {
        gst_adapter_clear (mpeg_dec->adapter);
        goto done;
    }

    if (mpeg_dec->vdp_info.slice_count > 0)
        ret = gst_vdp_mpeg_dec_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer),
                                       GST_BUFFER_SIZE (buffer));

done:
    gst_object_unref (mpeg_dec);

    return ret;
}
static gboolean
gst_rtp_mp4g_pay_parse_audio_config (GstRtpMP4GPay * rtpmp4gpay,
    GstBuffer * buffer)
{
  GstMapInfo map;
  guint8 objectType = 0;
  guint8 samplingIdx = 0;
  guint8 channelCfg = 0;
  GstBitReader br;

  gst_buffer_map (buffer, &map, GST_MAP_READ);

  gst_bit_reader_init (&br, map.data, map.size);

  /* any object type is fine, we need to copy it to the profile-level-id field. */
  if (!gst_bit_reader_get_bits_uint8 (&br, &objectType, 5))
    goto too_short;
  if (objectType == 0)
    goto invalid_object;

  if (!gst_bit_reader_get_bits_uint8 (&br, &samplingIdx, 4))
    goto too_short;
  /* only fixed values for now */
  if (samplingIdx > 12 && samplingIdx != 15)
    goto wrong_freq;

  if (!gst_bit_reader_get_bits_uint8 (&br, &channelCfg, 4))
    goto too_short;
  if (channelCfg > 7)
    goto wrong_channels;

  /* rtp rate depends on sampling rate of the audio */
  if (samplingIdx == 15) {
    guint32 rate = 0;

    /* index of 15 means we get the rate in the next 24 bits */
    if (!gst_bit_reader_get_bits_uint32 (&br, &rate, 24))
      goto too_short;

    rtpmp4gpay->rate = rate;
  } else {
    /* else use the rate from the table */
    rtpmp4gpay->rate = sampling_table[samplingIdx];
  }

  rtpmp4gpay->frame_len = 1024;

  switch (objectType) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 6:
    case 7:
    {
      guint8 frameLenFlag = 0;

      if (gst_bit_reader_get_bits_uint8 (&br, &frameLenFlag, 1))
        if (frameLenFlag)
          rtpmp4gpay->frame_len = 960;

      break;
    }
    default:
      break;
  }

  /* extra rtp params contain the number of channels */
  g_free (rtpmp4gpay->params);
  rtpmp4gpay->params = g_strdup_printf ("%d", channelCfg);
  /* audio stream type */
  rtpmp4gpay->streamtype = "5";
  /* mode only high bitrate for now */
  rtpmp4gpay->mode = "AAC-hbr";
  /* profile */
  g_free (rtpmp4gpay->profile);
  rtpmp4gpay->profile = g_strdup_printf ("%d", objectType);

  GST_DEBUG_OBJECT (rtpmp4gpay,
      "objectType: %d, samplingIdx: %d (%d), channelCfg: %d, frame_len %d",
      objectType, samplingIdx, rtpmp4gpay->rate, channelCfg,
      rtpmp4gpay->frame_len);

  gst_buffer_unmap (buffer, &map);
  return TRUE;

  /* ERROR */
too_short:
  {
    GST_ELEMENT_ERROR (rtpmp4gpay, STREAM, FORMAT,
        (NULL), ("config string too short"));
    gst_buffer_unmap (buffer, &map);
    return FALSE;
  }
invalid_object:
  {
    GST_ELEMENT_ERROR (rtpmp4gpay, STREAM, FORMAT,
        (NULL), ("invalid object type"));
    gst_buffer_unmap (buffer, &map);
    return FALSE;
  }
wrong_freq:
  {
    GST_ELEMENT_ERROR (rtpmp4gpay, STREAM, NOT_IMPLEMENTED,
        (NULL), ("unsupported frequency index %d", samplingIdx));
    gst_buffer_unmap (buffer, &map);
    return FALSE;
  }
wrong_channels:
  {
    GST_ELEMENT_ERROR (rtpmp4gpay, STREAM, NOT_IMPLEMENTED,
        (NULL), ("unsupported number of channels %d, must < 8", channelCfg));
    gst_buffer_unmap (buffer, &map);
    return FALSE;
  }
}