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; } }