uint8_t ADM_AudiocodecDCA::run(uint8_t *inptr, uint32_t nbIn, float *outptr, uint32_t *nbOut) { uint32_t avail; uint32_t length,syncoff; int flags = 0, samprate = 0, bitrate = 0, frame_length; uint8_t chan = _wavHeader->channels; *nbOut=0; // Ready to decode while(nbIn) { if(nbIn<DTS_HEADER_SIZE) { if(nbIn) printf("[DTS]: no data to decode avail %u\n",nbIn); break; } //length = ADM_DCAGetInfo(ptr,nbIn, &samprate, &bitrate, &chan,&syncoff,&flags); length = dts_syncinfo (DTS_HANDLE, inptr, &flags, &samprate,&bitrate, &frame_length); if(!length) { printf("[DTS] dts_syncinfo failed\n"); ADM_assert(0); } if(length>nbIn) { // not enough data break; } if (ch_route.mode < 1) { CHANNEL_TYPE *p_ch_type = ch_route.input_type; switch (flags & DTS_CHANNEL_MASK) { case DTS_MONO: *(p_ch_type++) = CH_MONO; break; case DTS_STEREO: *(p_ch_type++) = CH_FRONT_LEFT; *(p_ch_type++) = CH_FRONT_RIGHT; break; case DTS_3F2R: *(p_ch_type++) = CH_FRONT_CENTER; *(p_ch_type++) = CH_FRONT_LEFT; *(p_ch_type++) = CH_FRONT_RIGHT; *(p_ch_type++) = CH_REAR_LEFT; *(p_ch_type++) = CH_REAR_RIGHT; break; default: ADM_assert(0); } if (flags & DTS_LFE) { *(p_ch_type++) = CH_LFE; } } sample_t level = 1, bias = 0; flags &=DTS_CHANNEL_MASK; flags |= DTS_ADJUST_LEVEL; if (dts_frame(DTS_HANDLE, inptr, &flags, &level, bias)) { printf("\n DTS_frame failed!"); inptr+=length; nbIn-=length; outptr+=256*chan; *nbOut+=256*chan; break; }; inptr+=length; nbIn-=length; // Each block is 256 samples *nbOut += 256 * chan * dts_blocks_num(DTS_HANDLE); float *cur; for (int i = 0; i < dts_blocks_num(DTS_HANDLE); i++) { if (dts_block (DTS_HANDLE)) { printf("\n[DTS] dts_block failed on block %d/%d\n",i,dts_blocks_num (DTS_HANDLE)); // in that case we silent out the chunk memset(outptr, 0, 256 * chan * sizeof(float)); } else { float *cur; for (int k = 0; k < chan; k++) { sample_t *sample=(sample_t *)dts_samples(DTS_HANDLE); sample += 256 * k; cur = outptr + k; for (int j = 0; j < 256; j++) { *cur = *sample++; cur+=chan; } } } outptr += chan * 256; } } return 1; }
/***************************************************************************** * DoWork: decode a DTS frame. *****************************************************************************/ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf ) { filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; sample_t i_sample_level = 1; int i_flags = p_sys->i_flags; int i_bytes_per_block = 256 * p_sys->i_nb_channels * sizeof(float); int i; /* * Do the actual decoding now. */ /* Needs to be called so the decoder knows which type of bitstream it is * dealing with. */ int i_sample_rate, i_bit_rate, i_frame_length; if( !dts_syncinfo( p_sys->p_libdts, p_in_buf->p_buffer, &i_flags, &i_sample_rate, &i_bit_rate, &i_frame_length ) ) { msg_Warn( p_filter, "libdts couldn't sync on frame" ); p_out_buf->i_nb_samples = p_out_buf->i_nb_bytes = 0; return; } i_flags = p_sys->i_flags; dts_frame( p_sys->p_libdts, p_in_buf->p_buffer, &i_flags, &i_sample_level, 0 ); if ( (i_flags & DTS_CHANNEL_MASK) != (p_sys->i_flags & DTS_CHANNEL_MASK) && !p_sys->b_dontwarn ) { msg_Warn( p_filter, "libdts couldn't do the requested downmix 0x%x->0x%x", p_sys->i_flags & DTS_CHANNEL_MASK, i_flags & DTS_CHANNEL_MASK ); p_sys->b_dontwarn = 1; } if( 0)//!p_sys->b_dynrng ) { dts_dynrng( p_sys->p_libdts, NULL, NULL ); } for ( i = 0; i < dts_blocks_num(p_sys->p_libdts); i++ ) { sample_t * p_samples; if( dts_block( p_sys->p_libdts ) ) { msg_Warn( p_filter, "dts_block failed for block %d", i ); break; } p_samples = dts_samples( p_sys->p_libdts ); if ( (p_sys->i_flags & DTS_CHANNEL_MASK) == DTS_MONO && (p_filter->output.i_physical_channels & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) ) { Duplicate( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block), p_samples ); } else if ( p_filter->output.i_original_channels & AOUT_CHAN_REVERSESTEREO ) { Exchange( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block), p_samples ); } else { /* Interleave the *$£%ù samples. */ Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block), p_samples, p_sys->i_nb_channels, p_sys->pi_chan_table); } } p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_nb_bytes = i_bytes_per_block * i; }
static GstFlowReturn gst_dtsdec_handle_frame (GstDtsDec * dts, guint8 * data, guint length, gint flags, gint sample_rate, gint bit_rate) { gboolean need_renegotiation = FALSE; gint channels, num_blocks; GstBuffer *out; gint i, s, c, num_c; sample_t *samples; GstFlowReturn result = GST_FLOW_OK; /* go over stream properties, update caps/streaminfo if needed */ if (dts->sample_rate != sample_rate) { need_renegotiation = TRUE; dts->sample_rate = sample_rate; } dts->stream_channels = flags; if (bit_rate != dts->bit_rate) { dts->bit_rate = bit_rate; gst_dtsdec_update_streaminfo (dts); } if (dts->request_channels == DTS_CHANNEL) { GstCaps *caps; caps = gst_pad_get_allowed_caps (dts->srcpad); if (caps && gst_caps_get_size (caps) > 0) { GstCaps *copy = gst_caps_copy_nth (caps, 0); GstStructure *structure = gst_caps_get_structure (copy, 0); gint channels; const int dts_channels[6] = { DTS_MONO, DTS_STEREO, DTS_STEREO | DTS_LFE, DTS_2F2R, DTS_2F2R | DTS_LFE, DTS_3F2R | DTS_LFE, }; /* Prefer the original number of channels, but fixate to something * preferred (first in the caps) downstream if possible. */ gst_structure_fixate_field_nearest_int (structure, "channels", flags ? gst_dtsdec_channels (flags, NULL) : 6); gst_structure_get_int (structure, "channels", &channels); if (channels <= 6) dts->request_channels = dts_channels[channels - 1]; else dts->request_channels = dts_channels[5]; gst_caps_unref (copy); } else if (flags) { dts->request_channels = dts->stream_channels; } else { dts->request_channels = DTS_3F2R | DTS_LFE; } if (caps) gst_caps_unref (caps); } /* process */ flags = dts->request_channels | DTS_ADJUST_LEVEL; dts->level = 1; if (dts_frame (dts->state, data, &flags, &dts->level, dts->bias)) { GST_WARNING ("dts_frame error"); return GST_FLOW_OK; } channels = flags & (DTS_CHANNEL_MASK | DTS_LFE); if (dts->using_channels != channels) { need_renegotiation = TRUE; dts->using_channels = channels; } if (need_renegotiation == TRUE) { GST_DEBUG ("dtsdec: sample_rate:%d stream_chans:0x%x using_chans:0x%x", dts->sample_rate, dts->stream_channels, dts->using_channels); if (!gst_dtsdec_renegotiate (dts)) { GST_ELEMENT_ERROR (dts, CORE, NEGOTIATION, (NULL), (NULL)); return GST_FLOW_ERROR; } } if (dts->dynamic_range_compression == FALSE) { dts_dynrng (dts->state, NULL, NULL); } /* handle decoded data, one block is 256 samples */ num_blocks = dts_blocks_num (dts->state); for (i = 0; i < num_blocks; i++) { if (dts_block (dts->state)) { GST_WARNING ("dts_block error %d", i); continue; } samples = dts_samples (dts->state); num_c = gst_dtsdec_channels (dts->using_channels, NULL); result = gst_pad_alloc_buffer_and_set_caps (dts->srcpad, 0, (SAMPLE_WIDTH / 8) * 256 * num_c, GST_PAD_CAPS (dts->srcpad), &out); if (result != GST_FLOW_OK) break; GST_BUFFER_TIMESTAMP (out) = dts->current_ts; GST_BUFFER_DURATION (out) = GST_SECOND * 256 / dts->sample_rate; dts->current_ts += GST_BUFFER_DURATION (out); /* libdts returns buffers in 256-sample-blocks per channel, * we want interleaved. And we need to copy anyway... */ data = GST_BUFFER_DATA (out); for (s = 0; s < 256; s++) { for (c = 0; c < num_c; c++) { *(sample_t *) data = samples[s + c * 256]; data += (SAMPLE_WIDTH / 8); } } /* push on */ result = gst_pad_push (dts->srcpad, out); if (result != GST_FLOW_OK) break; } return result; }