static gboolean gst_dtsdec_start (GstAudioDecoder * dec) { GstDtsDec *dts = GST_DTSDEC (dec); GstDtsDecClass *klass; GST_DEBUG_OBJECT (dec, "start"); klass = GST_DTSDEC_CLASS (G_OBJECT_GET_CLASS (dts)); dts->state = dca_init (klass->dts_cpuflags); dts->samples = dca_samples (dts->state); dts->bit_rate = -1; dts->sample_rate = -1; dts->stream_channels = DCA_CHANNEL; dts->using_channels = DCA_CHANNEL; dts->level = 1; dts->bias = 0; dts->flag_update = TRUE; /* call upon legacy upstream byte support (e.g. seeking) */ gst_audio_decoder_set_estimate_rate (dec, TRUE); return TRUE; }
/*********************************************************************** * Decode *********************************************************************** * **********************************************************************/ static hb_buffer_t * Decode( hb_work_object_t * w ) { hb_work_private_t * pv = w->private_data; hb_buffer_t * buf; hb_audio_t * audio = w->audio; int i, j, k; int64_t pts, pos; uint64_t upts, upos; int num_blocks; /* Get a frame header if don't have one yet */ if( !pv->sync ) { while( hb_list_bytes( pv->list ) >= 14 ) { /* We have 14 bytes, check if this is a correct header */ hb_list_seebytes( pv->list, pv->frame, 14 ); pv->size = dca_syncinfo( pv->state, pv->frame, &pv->flags_in, &pv->rate, &pv->bitrate, &pv->frame_length ); if( pv->size ) { /* It is. W00t. */ if( pv->error ) { hb_log( "dca_syncinfo ok" ); } pv->error = 0; pv->sync = 1; break; } /* It is not */ if( !pv->error ) { hb_log( "dca_syncinfo failed" ); pv->error = 1; } /* Try one byte later */ hb_list_getbytes( pv->list, pv->frame, 1, NULL, NULL ); } } if( !pv->sync || hb_list_bytes( pv->list ) < pv->size ) { /* Need more data */ return NULL; } /* Get the whole frame */ hb_list_getbytes( pv->list, pv->frame, pv->size, &upts, &upos ); pts = (int64_t)upts; pos = (int64_t)upos; if ( pts != pv->last_buf_pts ) { pv->last_buf_pts = pts; } else { // spec says that the PTS is the start time of the first frame // that starts in the PES frame so we only use the PTS once then // get the following frames' PTS from the frame length. pts = -1; } // mkv files typically use a 1ms timebase which results in a lot of // truncation error in their timestamps. Also, TSMuxer or something // in the m2ts-to-mkv toolchain seems to take a very casual attitude // about time - timestamps seem to randomly offset by ~40ms for a few // seconds then recover. So, if the pts we got is within 50ms of the // pts computed from the data stream, use the data stream pts. if ( pts == -1 || ( pv->next_pts && fabs( pts - pv->next_pts ) < 50.*90. ) ) { pts = pv->next_pts; } double frame_dur = (double)(pv->frame_length & ~0xFF) / (double)pv->rate * 90000.; /* DCA passthrough: don't decode the DCA frame */ if( audio->config.out.codec == HB_ACODEC_DCA_PASS ) { buf = hb_buffer_init( pv->size ); memcpy( buf->data, pv->frame, pv->size ); buf->start = pts; pv->next_pts = pts + frame_dur; buf->stop = pv->next_pts; pv->sync = 0; return buf; } /* Feed libdca */ dca_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 ); /* find out how many blocks are in this frame */ num_blocks = dca_blocks_num( pv->state ); /* num_blocks blocks per frame, 256 samples per block, channelsused channels */ int nsamp = num_blocks * 256; buf = hb_buffer_init( nsamp * pv->out_discrete_channels * sizeof( float ) ); buf->start = pts; pv->next_pts = pts + (double)nsamp / (double)pv->rate * 90000.; buf->stop = pv->next_pts; for( i = 0; i < num_blocks; i++ ) { dca_sample_t * samples_in; float * samples_out; dca_block( pv->state ); samples_in = dca_samples( pv->state ); samples_out = ((float *) buf->data) + 256 * pv->out_discrete_channels * i; /* Interleave */ for( j = 0; j < 256; j++ ) { for ( k = 0; k < pv->out_discrete_channels; k++ ) { samples_out[(pv->out_discrete_channels*j)+k] = samples_in[(256*k)+j] * 32767; } } } pv->sync = 0; return buf; }
static int Decode( decoder_t *p_dec, block_t *p_in_buf ) { decoder_sys_t *p_sys = p_dec->p_sys; if (p_in_buf == NULL) /* No Drain */ return VLCDEC_SUCCESS; sample_t i_sample_level = 1; int i_flags = p_sys->i_flags; size_t i_bytes_per_block = 256 * p_sys->i_nb_channels * sizeof(float); block_t *p_out_buf = block_Alloc( 6 * i_bytes_per_block ); if( unlikely(p_out_buf == NULL) ) goto out; /* * 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( !dca_syncinfo( p_sys->p_libdca, p_in_buf->p_buffer, &i_flags, &i_sample_rate, &i_bit_rate, &i_frame_length ) ) { msg_Warn( p_dec, "libdca couldn't sync on frame" ); p_out_buf->i_nb_samples = p_out_buf->i_buffer = 0; goto out; } i_flags = p_sys->i_flags; dca_frame( p_sys->p_libdca, p_in_buf->p_buffer, &i_flags, &i_sample_level, 0 ); if ( (i_flags & DCA_CHANNEL_MASK) != (p_sys->i_flags & DCA_CHANNEL_MASK) && !p_sys->b_dontwarn ) { msg_Warn( p_dec, "libdca couldn't do the requested downmix 0x%x->0x%x", p_sys->i_flags & DCA_CHANNEL_MASK, i_flags & DCA_CHANNEL_MASK ); p_sys->b_dontwarn = 1; } if( 0)//!p_sys->b_dynrng ) { dca_dynrng( p_sys->p_libdca, NULL, NULL ); } for( int i = 0; i < dca_blocks_num(p_sys->p_libdca); i++ ) { sample_t * p_samples; if( dca_block( p_sys->p_libdca ) ) { msg_Warn( p_dec, "dca_block failed for block %d", i ); break; } p_samples = dca_samples( p_sys->p_libdca ); if ( (p_sys->i_flags & DCA_CHANNEL_MASK) == DCA_MONO && (p_dec->fmt_out.audio.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_dec->fmt_out.audio.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 = dca_blocks_num(p_sys->p_libdca) * 256; p_out_buf->i_buffer = p_in_buf->i_nb_samples * sizeof(float) * p_sys->i_nb_channels; p_out_buf->i_dts = p_in_buf->i_dts; p_out_buf->i_pts = p_in_buf->i_pts; p_out_buf->i_length = p_in_buf->i_length; out: if (p_out_buf != NULL) decoder_QueueAudio(p_dec, p_out_buf); block_Release( p_in_buf ); return VLCDEC_SUCCESS; }
HRESULT TaudioCodecLibDTS::decode(TbyteBuffer &src) { unsigned char *p = src.size() ? &src[0] : NULL; unsigned char *base = p; unsigned char *end = p + src.size(); while (end - p >= 14) { int size = 0, flags, sample_rate, frame_length, bit_rate; if ((size = dca_syncinfo(state, p, &flags, &sample_rate, &bit_rate, &frame_length)) > 0) { bool enoughData = p + size <= end; if (enoughData) { if (codecId == CODEC_ID_SPDIF_DTS) { bpssum += (lastbps = bit_rate / 1000); numframes++; BYTE type; switch (frame_length) { case 512: type = 0x0b; break; case 1024: type = 0x0c; break; default : type = 0x0d; break; } HRESULT hr = deciA->deliverSampleBistream(p, size, bit_rate, sample_rate, true, frame_length, 0); if (hr != S_OK) { return hr; } } else { flags |= DCA_ADJUST_LEVEL; libdca::sample_t level = 1, bias = 0; if (dca_frame(state, p, &flags, &level, bias) == 0) { bpssum += (lastbps = bit_rate / 1000); numframes++; // Dynamic range compression - Not suppored yet by libdts if (deci->getParam2(IDFF_audio_decoder_DRC)) { libdca::sample_t drcLevel = ((libdca::sample_t)deci->getParam2(IDFF_audio_decoder_DRC_Level) / 100); if (drcLevel <= 0.5) { dca_dynrng(state, NULL, NULL); } } else { dca_dynrng(state, NULL, NULL); } int scmapidx = std::min(flags & DCA_CHANNEL_MASK, int(countof(scmaps) / 2)); const Tscmap &scmap = scmaps[scmapidx + ((flags & DCA_LFE) ? (countof(scmaps) / 2) : 0)]; int blocks = dca_blocks_num(state); float *dst0, *dst; dst0 = dst = (float*)getDst(blocks * 256 * scmap.nchannels * sizeof(float)); int i = 0; for (; i < blocks && dca_block(state) == 0; i++) { libdca::sample_t* samples = dca_samples(state); for (int j = 0; j < 256; j++, samples++) for (int ch = 0; ch < scmap.nchannels; ch++) { *dst++ = float(*(samples + 256 * scmap.ch[ch]) / level); } } if (i == blocks) { fmt.sf = TsampleFormat::SF_FLOAT32; fmt.freq = sample_rate; fmt.setChannels(scmap.nchannels, scmap.channelMask); HRESULT hr = sinkA->deliverDecodedSample(dst0, blocks * 256, fmt); if (hr != S_OK) { return hr; } } } } p += size; } memmove(base, p, end - p); end = base + (end - p); p = base; if (!enoughData) { break; } } else { p++; } } src.resize(end - p); return S_OK; }