/** * gst_bit_reader_init_from_buffer: * @reader: a #GstBitReader instance * @buffer: (transfer none): Buffer from which the #GstBitReader should read * * Initializes a #GstBitReader instance to read from @buffer. This function * can be called on already initialized instances. * * Since: 0.10.22 */ void gst_bit_reader_init_from_buffer (GstBitReader * reader, const GstBuffer * buffer) { g_return_if_fail (GST_IS_BUFFER (buffer)); gst_bit_reader_init (reader, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); }
static gboolean gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf, gint skip, guint * framesize, guint * rate, guint * chans, guint * blocks, guint * sid, gboolean * eac) { GstBitReader bits; guint16 sync; guint8 bsid; GstMapInfo map; gboolean ret = FALSE; gst_buffer_map (buf, &map, GST_MAP_READ); gst_bit_reader_init (&bits, map.data, map.size); GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", map.data, MIN (map.size, 16)); gst_bit_reader_skip_unchecked (&bits, skip * 8); sync = gst_bit_reader_get_bits_uint16_unchecked (&bits, 16); gst_bit_reader_skip_unchecked (&bits, 16 + 8); bsid = gst_bit_reader_peek_bits_uint8_unchecked (&bits, 5); if (G_UNLIKELY (sync != 0x0b77)) goto cleanup; GST_LOG_OBJECT (parse, "bsid = %d", bsid); if (bsid <= 10) { if (eac) *eac = FALSE; ret = gst_ac3_parse_frame_header_ac3 (parse, buf, skip, framesize, rate, chans, blocks, sid); goto cleanup; } else if (bsid <= 16) { if (eac) *eac = TRUE; ret = gst_ac3_parse_frame_header_eac3 (parse, buf, skip, framesize, rate, chans, blocks, sid); goto cleanup; } else { GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid); ret = FALSE; goto cleanup; } GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid); cleanup: gst_buffer_unmap (buf, &map); return ret; }
static gboolean gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf, gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid) { GstBitReader bits; GstMapInfo map; guint8 fscod, frmsizcod, bsid, acmod, lfe_on, rate_scale; gboolean ret = FALSE; GST_LOG_OBJECT (ac3parse, "parsing ac3"); gst_buffer_map (buf, &map, GST_MAP_READ); gst_bit_reader_init (&bits, map.data, map.size); gst_bit_reader_skip_unchecked (&bits, skip * 8); gst_bit_reader_skip_unchecked (&bits, 16 + 16); fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); frmsizcod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 6); if (G_UNLIKELY (fscod == 3 || frmsizcod >= G_N_ELEMENTS (frmsizcod_table))) { GST_DEBUG_OBJECT (ac3parse, "bad fscod=%d frmsizcod=%d", fscod, frmsizcod); goto cleanup; } bsid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 5); gst_bit_reader_skip_unchecked (&bits, 3); /* bsmod */ acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); /* spec not quite clear here: decoder should decode if less than 8, * but seemingly only defines 6 and 8 cases */ /* Files with 9 and 10 happen, and seem to comply with the <= 8 format, so let them through. The spec says nothing about 9 and 10 */ if (bsid > 10) { GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid); goto cleanup; } else if (bsid != 8 && bsid != 6) { GST_DEBUG_OBJECT (ac3parse, "undefined bsid=%d", bsid); } if ((acmod & 0x1) && (acmod != 0x1)) /* 3 front channels */ gst_bit_reader_skip_unchecked (&bits, 2); if ((acmod & 0x4)) /* if a surround channel exists */ gst_bit_reader_skip_unchecked (&bits, 2); if (acmod == 0x2) /* if in 2/0 mode */ gst_bit_reader_skip_unchecked (&bits, 2); lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1); /* 6/8->0, 9->1, 10->2, see http://matroska.org/technical/specs/codecid/index.html */ rate_scale = (CLAMP (bsid, 8, 10) - 8); if (frame_size) *frame_size = frmsizcod_table[frmsizcod].frame_size[fscod] * 2; if (rate) *rate = fscod_rates[fscod] >> rate_scale; if (chans) *chans = acmod_chans[acmod] + lfe_on; if (blks) *blks = 6; if (sid) *sid = 0; ret = TRUE; cleanup: gst_buffer_unmap (buf, &map); return ret; }
static gboolean gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf, gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid) { GstBitReader bits; GstMapInfo map; guint16 frmsiz, sample_rate, blocks; guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod; gboolean ret = FALSE; GST_LOG_OBJECT (ac3parse, "parsing e-ac3"); gst_buffer_map (buf, &map, GST_MAP_READ); gst_bit_reader_init (&bits, map.data, map.size); gst_bit_reader_skip_unchecked (&bits, skip * 8); gst_bit_reader_skip_unchecked (&bits, 16); strmtyp = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* strmtyp */ if (G_UNLIKELY (strmtyp == 3)) { GST_DEBUG_OBJECT (ac3parse, "bad strmtyp %d", strmtyp); goto cleanup; } strmid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); /* substreamid */ frmsiz = gst_bit_reader_get_bits_uint16_unchecked (&bits, 11); /* frmsiz */ fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* fscod */ if (fscod == 3) { fscod2 = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* fscod2 */ if (G_UNLIKELY (fscod2 == 3)) { GST_DEBUG_OBJECT (ac3parse, "invalid fscod2"); goto cleanup; } sample_rate = fscod_rates[fscod2] / 2; blocks = 6; } else { numblkscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* numblkscod */ sample_rate = fscod_rates[fscod]; blocks = numblks[numblkscod]; } acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); /* acmod */ lfe_on = gst_bit_reader_get_bits_uint8_unchecked (&bits, 1); /* lfeon */ gst_bit_reader_skip_unchecked (&bits, 5); /* bsid */ if (frame_size) *frame_size = (frmsiz + 1) * 2; if (rate) *rate = sample_rate; if (chans) *chans = acmod_chans[acmod] + lfe_on; if (blks) *blks = blocks; if (sid) *sid = (strmtyp & 0x1) << 3 | strmid; ret = TRUE; cleanup: gst_buffer_unmap (buf, &map); 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; } }