/* * Copyright (C) 2000-2001 the xine project * * This file is part of xine, a unix video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * $Id: xine_decoder.c,v 1.43 2003/05/27 14:31:24 jcdutton Exp $ * * 04-09-2001 DTS passtrough (C) Joachim Koenig * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton * */ #ifndef __sun /* required for swab() */ #define _XOPEN_SOURCE 500 #endif #include #include #include #include #include #include #include /* ntohs */ #include #include "xine_internal.h" #include "audio_out.h" #include "buffer.h" /* #define LOG_DEBUG */ /* #define ENABLE_DTS_PARSE */ typedef struct { audio_decoder_class_t decoder_class; } dts_class_t; typedef struct dts_decoder_s { audio_decoder_t audio_decoder; xine_stream_t *stream; audio_decoder_class_t *class; uint32_t rate; uint32_t bits_per_sample; uint32_t number_of_channels; int output_open; } dts_decoder_t; #ifdef ENABLE_DTS_PARSE typedef struct { uint8_t *start; uint32_t byte_position; uint32_t bit_position; uint8_t byte; } getbits_state_t; static float AdjTable[] = { 1.0000, 1.1250, 1.2500, 1.4375 }; static int32_t getbits_init(getbits_state_t *state, uint8_t *start) { if ((state == NULL) || (start == NULL)) return -1; state->start = start; state->bit_position = 0; state->byte_position = 0; state->byte = start[0]; return 0; } /* Non-optimized getbits. */ /* This can easily be optimized for particular platforms. */ static uint32_t getbits(getbits_state_t *state, uint32_t number_of_bits) { uint32_t result=0; uint8_t byte=0; if (number_of_bits > 32) { printf("Number of bits > 32 in getbits\n"); assert(0); } if ((state->bit_position) > 0) { /* Last getbits left us in the middle of a byte. */ if (number_of_bits > (8-state->bit_position)) { /* this getbits will span 2 or more bytes. */ byte = state->byte; byte = byte >> (state->bit_position); result = byte; number_of_bits -= (8-state->bit_position); state->bit_position = 0; state->byte_position++; state->byte = state->start[state->byte_position]; } else { byte=state->byte; state->byte = state->byte << number_of_bits; byte = byte >> (8 - number_of_bits); result = byte; state->bit_position += number_of_bits; /* Here it is impossible for bit_position > 8 */ if (state->bit_position == 8) { state->bit_position = 0; state->byte_position++; state->byte = state->start[state->byte_position]; } number_of_bits = 0; } } if ((state->bit_position) == 0) while (number_of_bits > 7) { result = (result << 8) + state->byte; state->byte_position++; state->byte = state->start[state->byte_position]; number_of_bits -= 8; } if (number_of_bits > 0) { /* number_of_bits < 8 */ byte = state->byte; state->byte = state->byte << number_of_bits; state->bit_position += number_of_bits; /* Here it is impossible for bit_position > 7 */ if (state->bit_position > 7) printf ("bit_pos2 too large: %d\n",state->bit_position); byte = byte >> (8 - number_of_bits); result = (result << number_of_bits) + byte; number_of_bits = 0; } return result; } /* Used by dts.wav files, only 14 bits of the 16 possible are used in the CD. */ static void squash14to16(uint8_t *buf_from, uint8_t *buf_to, uint32_t number_of_bytes) { int32_t from; int32_t to=0; uint16_t sample1; uint16_t sample2; uint16_t sample3; uint16_t sample4; uint16_t sample16bit; /* This should convert the 14bit sync word into a 16bit one. */ printf("libdts: squashing %d bytes.\n", number_of_bytes); for(from=0;from> 2); sample2 = buf_from[from+2] | buf_from[from+3] << 8; sample2 = (sample2 & 0x1fff) | ((sample2 & 0x8000) >> 2); sample16bit = (sample1 << 2) | (sample2 >> 12); buf_to[to++] = sample16bit >> 8; /* Add some swabbing in as well */ buf_to[to++] = sample16bit & 0xff; sample3 = buf_from[from+4] | buf_from[from+5] << 8; sample3 = (sample3 & 0x1fff) | ((sample3 & 0x8000) >> 2); sample16bit = ((sample2 & 0xfff) << 4) | (sample3 >> 10); buf_to[to++] = sample16bit >> 8; /* Add some swabbing in as well */ buf_to[to++] = sample16bit & 0xff; sample4 = buf_from[from+6] | buf_from[from+7] << 8; sample4 = (sample4 & 0x1fff) | ((sample4 & 0x8000) >> 2); sample16bit = ((sample3 & 0x3ff) << 6) | (sample4 >> 8); buf_to[to++] = sample16bit >> 8; /* Add some swabbing in as well */ buf_to[to++] = sample16bit & 0xff; buf_to[to++] = sample4 & 0xff; } } #endif void dts_reset (audio_decoder_t *this_gen) { /* dts_decoder_t *this = (dts_decoder_t *) this_gen; */ } void dts_discontinuity (audio_decoder_t *this_gen) { } #ifdef ENABLE_DTS_PARSE #if 0 /* FIXME: Make this re-entrant */ void InverseADPCM(void) { /* * NumADPCMCoeff =4, the number of ADPCM coefficients. * raADPCMcoeff[] are the ADPCM coefficients extracted * from the bit stream. * raSample[NumADPCMCoeff], ..., raSample[-1] are the * history from last subframe or subsubframe. It must * updated each time before reverse ADPCM is run for a * block of samples for each subband. */ for (m=0; mcontent; getbits_state_t state; uint32_t sync_type=0; uint8_t frame_type; uint8_t deficit_sample_count; uint8_t crc_present_flag; uint8_t number_of_pcm_blocks; uint16_t primary_frame_byte_size; uint8_t audio_channel_arrangement; uint8_t core_audio_sampling_frequency; uint8_t transmission_bit_rate; uint8_t embedded_down_mix_enabled; uint8_t embedded_dynamic_range_flag; uint8_t embedded_time_stamp_flag; uint8_t auxiliary_data_flag; uint8_t hdcd; uint8_t extension_audio_descriptor_flag; uint8_t extended_coding_flag; uint8_t audio_sync_word_insertion_flag; uint8_t low_frequency_effects_flag; uint8_t predictor_history_flag_switch; uint16_t header_crc_check_bytes=0; uint8_t multirate_interpolator_switch; uint8_t encoder_software_revision; uint8_t copy_history; uint8_t source_pcm_resolution; uint8_t front_sum_difference_flag; uint8_t surrounds_sum_difference_flag; int8_t dialog_normalisation_parameter; int8_t dialog_normalisation_unspecified; int8_t dialog_normalisation_gain; int8_t number_of_subframes; int8_t number_of_primary_audio_channels; int8_t subband_activity_count[8]; int8_t high_frequency_VQ_start_subband[8]; int8_t joint_intensity_coding_index[8]; int8_t transient_mode_code_book[8]; int8_t scales_factor_code_book[8]; int8_t bit_allocation_quantizer_select[8]; int8_t quantization_index_codebook_select[8][26]; float scale_factor_adjustment_index[8][10]; uint16_t audio_header_crc_check_word; int32_t nVQIndex; int32_t nQSelect; int8_t subsubframe_count; int8_t partial_subsubframe_sample_count; int8_t prediction_mode[8][33]; uint32_t channel_extension_sync_word; uint16_t extension_primary_frame_byte_size; uint8_t extension_channel_arrangement; uint32_t extension_sync_word_SYNC96; uint16_t extension_frame_byte_data_size_FSIZE96; uint8_t revision_number; int32_t n, ch, i; printf("libdts: buf->size = %d\n", buf->size); printf("libdts: parse1: "); for(i=0;i<16;i++) { printf("%02x ",data_in[i]); } printf("\n"); if ((data_in[0] == 0x7f) && (data_in[1] == 0xfe) && (data_in[2] == 0x80) && (data_in[3] == 0x01)) { sync_type=1; } if (data_in[0] == 0xff && data_in[1] == 0x1f && data_in[2] == 0x00 && data_in[3] == 0xe8 && data_in[4] == 0xf1 && /* DTS standard document was wrong here! */ data_in[5] == 0x07 ) { /* DTS standard document was wrong here! */ squash14to16(&data_in[0], &data_in[0], buf->size); buf->size = buf->size - (buf->size / 8); /* size = size * 7 / 8; */ sync_type=2; } if (sync_type == 0) { printf("libdts: DTS Sync bad\n"); return; } printf("libdts: DTS Sync OK. type=%d\n", sync_type); printf("libdts: parse2: "); for(i=0;i<16;i++) { printf("%02x ",data_in[i]); } printf("\n"); getbits_init(&state, &data_in[4]); /* B.2 Unpack Frame Header Routine */ /* Frame Type V FTYPE 1 bit */ frame_type = getbits(&state, 1); /* 1: Normal Frame, 2:Termination Frame */ /* Deficit Sample Count V SHORT 5 bits */ deficit_sample_count = getbits(&state, 5); /* CRC Present Flag V CPF 1 bit */ crc_present_flag = getbits(&state, 1); /* Number of PCM Sample Blocks V NBLKS 7 bits */ number_of_pcm_blocks = getbits(&state, 7); /* Primary Frame Byte Size V FSIZE 14 bits */ primary_frame_byte_size = getbits(&state, 14); /* Audio Channel Arrangement ACC AMODE 6 bits */ audio_channel_arrangement = getbits(&state, 6); /* Core Audio Sampling Frequency ACC SFREQ 4 bits */ core_audio_sampling_frequency = getbits(&state, 4); /* Transmission Bit Rate ACC RATE 5 bits */ transmission_bit_rate = getbits(&state, 5); /* Embedded Down Mix Enabled V MIX 1 bit */ embedded_down_mix_enabled = getbits(&state, 1); /* Embedded Dynamic Range Flag V DYNF 1 bit */ embedded_dynamic_range_flag = getbits(&state, 1); /* Embedded Time Stamp Flag V TIMEF 1 bit */ embedded_time_stamp_flag = getbits(&state, 1); /* Auxiliary Data Flag V AUXF 1 bit */ auxiliary_data_flag = getbits(&state, 1); /* HDCD NV HDCD 1 bits */ hdcd = getbits(&state, 1); /* Extension Audio Descriptor Flag ACC EXT_AUDIO_ID 3 bits */ extension_audio_descriptor_flag = getbits(&state, 3); /* Extended Coding Flag ACC EXT_AUDIO 1 bit */ extended_coding_flag = getbits(&state, 1); /* Audio Sync Word Insertion Flag ACC ASPF 1 bit */ audio_sync_word_insertion_flag = getbits(&state, 1); /* Low Frequency Effects Flag V LFF 2 bits */ low_frequency_effects_flag = getbits(&state, 2); /* Predictor History Flag Switch V HFLAG 1 bit */ predictor_history_flag_switch = getbits(&state, 1); /* Header CRC Check Bytes V HCRC 16 bits */ if (crc_present_flag == 1) header_crc_check_bytes = getbits(&state, 16); /* Multirate Interpolator Switch NV FILTS 1 bit */ multirate_interpolator_switch = getbits(&state, 1); /* Encoder Software Revision ACC/NV VERNUM 4 bits */ encoder_software_revision = getbits(&state, 4); /* Copy History NV CHIST 2 bits */ copy_history = getbits(&state, 2); /* Source PCM Resolution ACC/NV PCMR 3 bits */ source_pcm_resolution = getbits(&state, 3); /* Front Sum/Difference Flag V SUMF 1 bit */ front_sum_difference_flag = getbits(&state, 1); /* Surrounds Sum/Difference Flag V SUMS 1 bit */ surrounds_sum_difference_flag = getbits(&state, 1); /* Dialog Normalisation Parameter/Unspecified V DIALNORM/UNSPEC 4 bits */ switch (encoder_software_revision) { case 6: dialog_normalisation_unspecified = 0; dialog_normalisation_parameter = getbits(&state, 4); dialog_normalisation_gain = - (16+dialog_normalisation_parameter); break; case 7: dialog_normalisation_unspecified = 0; dialog_normalisation_parameter = getbits(&state, 4); dialog_normalisation_gain = - (dialog_normalisation_parameter); break; default: dialog_normalisation_unspecified = getbits(&state, 4); dialog_normalisation_gain = dialog_normalisation_parameter = 0; break; } /* B.3 Audio Decoding */ /* B.3.1 Primary Audio Coding Header */ /* Number of Subframes V SUBFS 4 bits */ number_of_subframes = getbits(&state, 4) + 1 ; /* Number of Primary Audio Channels V PCHS 3 bits */ number_of_primary_audio_channels = getbits(&state, 3) + 1 ; /* Subband Activity Count V SUBS 5 bits per channel */ for (ch=0; ch0 ) { /* Transmitted only when ADPCM active */ /* Extract the VQindex */ nVQIndex = getbits(&state,12); /* Look up the VQ table for prediction coefficients. */ /* FIXME: How to implement LookUp? */ /* FIXME: We don't have the ADPCMCoeff table. */ /* ADPCMCoeffVQ.LookUp(nVQIndex, PVQ[ch][n]);*/ /* 4 coefficients FIXME: Need to work out what this does. */ } } } /* Bit Allocation Index V ABITS variable bits */ /* FIXME: No getbits here InverseQ does the getbits */ for (ch=0; chInverseQ(&state, bit_allocation_index[ch][n]); */ } } #if 0 /* FIXME: ALL CODE BELOW HERE does not compile yet. */ /* Transition Mode V TMODE variable bits */ /* Always assume no transition unless told */ int32_t nQSelect; for (ch=0; ch1 ) { /* Transient possible only if more than one subsubframe. */ for (ch=0; ch0 ) { /* Present only if bits allocated */ /* Use codebook nQSelect to decode transition_mode from the bit stream */ /* FIXME: What is Inverse Quantization(InverseQ) ? */ QTMODE.ppQ[nQSelect]->InverseQ(InputFrame,transition_mode[ch][n]); } } } } } /* Scale Factors V SCALES variable bits */ for (ch=0; ch0 ) { /* Not present if no bit allocated */ /* * First scale factor */ /* Use the (Huffman) code indicated by nQSelect to decode */ /* the quantization index of scale_factors from the bit stream */ /* FIXME: What is Inverse Quantization(InverseQ) ? */ QSCALES.ppQ[nQSelect]->InverseQ(InputFrame, nScale); /* Take care of difference encoding */ if ( nQSelect < 5 ) { /* Huffman encoded, nScale is the difference */ nScaleSum += nScale; /* of the quantization indexes of scale_factors. */ } else { /* Otherwise, nScale is the quantization */ nScaleSum = nScale; /* level of scale_factors. */ } /* Look up scale_factors from the root square table */ /* FIXME: How to implement LookUp? */ pScaleTable->LookUp(nScaleSum, scale_factors[ch][n][0]) /* * Two scale factors transmitted if there is a transient */ if (transition_mode[ch][n]>0) { /* Use the (Huffman) code indicated by nQSelect to decode */ /* the quantization index of scale_factors from the bit stream */ /* FIXME: What is Inverse Quantization(InverseQ) ? */ QSCALES.ppQ[nQSelect]->InverseQ(InputFrame, nScale); /* Take care of difference encoding */ if ( nQSelect < 5 ) /* Huffman encoded, nScale is the difference */ nScaleSum += nScale; /* of the quantization indexes of scale_factors. */ else /* Otherwise, nScale is the quantization */ nScaleSum = nScale; /* level of scale_factors. */ /* Look up scale_factors from the root square table */ /* FIXME: How to implement LookUp? */ pScaleTable->LookUp(nScaleSum, scale_factors[ch][n][1]); } } } /* * High frequency VQ subbands */ for (n=high_frequency_VQ_start_subband[ch]; nInverseQ(InputFrame, nScale); /* Take care of difference encoding */ if ( nQSelect < 5 ) /* Huffman encoded, nScale is the difference */ nScaleSum += nScale; /* of the quantization indexes of scale_factors. */ else /* Otherwise, nScale is the quantization */ nScaleSum = nScale; /* level of scale_factors. */ /* Look up scale_factors from the root square table */ /* FIXME: How to implement LookUp? */ pScaleTable->LookUp(nScaleSum, scale_factors[ch][n][0]) } } /* Joint Subband Scale Factor Codebook Select V JOIN SHUFF 3 bits per channel */ for (ch=0; ch0 ) /* Transmitted only if joint subband coding enabled. */ joint_subband_scale_factor_codebook_select[ch] = getbits(&state,3); /* Scale Factors for Joint Subband Coding V JOIN SCALES variable bits */ int nSourceCh; for (ch=0; ch0 ) { /* Only if joint subband coding enabled. */ nSourceCh = joint_intensity_coding_index[ch]-1; /* Get source channel. joint_intensity_coding_index counts */ /* channels as 1,2,3,4,5, so minus 1. */ nQSelect = joint_subband_scale_factor_codebook_select[ch]; /* Select code book. */ for (n=subband_activity_count[ch]; nInverseQ(InputFrame, nJScale); /* Bias by 64 */ nJScale = nJScale + 64; /* Look up scale_factors_for_joint_subband_coding from the joint scale table */ /* FIXME: How to implement LookUp? */ JScaleTbl.LookUp(nJScale, scale_factors_for_joint_subband_coding[ch][n]); } } } /* Stereo Down-Mix Coefficients NV DOWN 7 bits per coefficient */ if ( (MIX!=0) && (number_of_primary_audio_channels>2) ) { /* Extract down mix indexes */ for (ch=0; ch0 ) { /* Present only if flagged by low_frequency_effects_flag */ /* extract low_frequency_effect_data samples from the bit stream */ for (n=0; n<2*low_frequency_effects_flag*subsubframe_count; n++) { low_frequency_effect_data[n] = (signed int)(signed char)getbits(&state,8); /* Use char to get sign extension because it */ /* is 8-bit 2's compliment. */ /* Extract scale factor index from the bit stream */ } LFEscaleIndex = getbits(&state,8); /* Look up the 7-bit root square quantization table */ /* FIXME: How to implement LookUp? */ pLFE_RMS->LookUp(LFEscaleIndex,nScale); /* Account for the quantizer step size which is 0.035 */ rScale = nScale*0.035; /* Get the actual low_frequency_effect_data samples */ for (n=0; n<2*low_frequency_effects_flag*subsubframe_count; n++) { LFECh.rLFE[k] = low_frequency_effect_data[n]*rScale; } /* Interpolation low_frequency_effect_data samples */ LFECh.InterpolationFIR(low_frequency_effects_flag); /* low_frequency_effects_flag indicates which */ /* interpolation filter to use */ } /* Audio Data V AUDIO variable bits */ /* * Select quantization step size table */ if ( RATE == 0x1f ) { pStepSizeTable = &StepSizeLossLess; /* Lossless quantization */ } else { pStepSizeTable = &StepSizeLossy; /* Lossy */ } /* * Unpack the subband samples */ for (nSubSubFrame=0; nSubSubFrameppQ[nSEL]->InverseQ(InputFrame,AUDIO[m]); break; case 2: /* No further encoding */ for (m=0; m<8; m++) { /* Extract quantization index from the bit stream */ /* FIXME: What is Inverse Quantization(InverseQ) ? */ pCQGroup->ppQ[nSEL]->InverseQ(InputFrame, nCode) /* Take care of 2's compliment */ AUDIO[m] = pCQGroup->ppQ[nSEL]->SignExtension(nCode); } break; case 3: /* Block code */ /* Block code is just 1 value with 4 samples derived from it. * with each sample a digit from the number (using a base derived from nABITS via a table) * E.g. nABITS = 10, base = 5 (Base value taken from table.) * 1st sample = (value % 5) - (int(5/2); (Values between -2 and +2 ) * 2st sample = ((value / 5) % 5) - (int(5/2); * 3rd sample = ((value / 25) % 5) - (int(5/2); * 4th sample = ((value / 125) % 5) - (int(5/2); * */ pCBQ = &pCBlockQ[nABITS-1]; /* Select block code book */ m = 0; for (nBlock=0; nBlock<2; nBlock++) { /* Extract the block code index from the bit stream */ /* FIXME: What is Inverse Quantization(InverseQ) ? */ pCQGroup->ppQ[nSEL]->InverseQ(InputFrame, nCode) /* Look up 4 samples from the block code book */ /* FIXME: How to implement LookUp? */ pCBQ->LookUp(nCode,&AUDIO[m]) m += 4; } break; default: /* Undefined */ printf("ERROR: Unknown AUDIO quantization index code book."); } /* * Account for quantization step size and scale factor */ /* Look up quantization step size */ nABITS = bit_allocation_index[ch][n]; /* FIXME: How to implement LookUp? */ pStepSizeTable->LookUp(nABITS, rStepSize); /* Identify transient location */ nTmode = transition_mode[ch][n]; if ( nTmode == 0 ) /* No transient */ nTmode = subsubframe_count; /* Determine proper scale factor */ if (nSubSubFramecontent; uint8_t *data_out; audio_buffer_t *audio_buffer; uint32_t ac5_pcm_samples; uint32_t ac5_spdif_type=0; uint32_t ac5_length=0; uint32_t ac5_pcm_length; uint32_t number_of_frames; uint32_t first_access_unit; int n; #ifdef LOG_DEBUG printf("libdts: DTS decode_data called.\n"); #endif #ifdef ENABLE_DTS_PARSE dts_parse_data (this, buf); #endif if ((this->stream->audio_out->get_capabilities(this->stream->audio_out) & AO_CAP_MODE_AC5) == 0) { return; } if (!this->output_open) { this->output_open = (this->stream->audio_out->open (this->stream->audio_out, this->stream, this->bits_per_sample, this->rate, AO_CAP_MODE_AC5)); } if (!this->output_open) return; if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; number_of_frames = buf->decoder_info[1]; /* Number of frames */ first_access_unit = buf->decoder_info[2]; /* First access unit */ if (number_of_frames > 2) { return; } for(n=1;n<=number_of_frames;n++) { data_in += ac5_length; if(data_in >= (buf->content+buf->size)) { printf("libdts: DTS length error\n"); return; } if ((data_in[0] != 0x7f) || (data_in[1] != 0xfe) || (data_in[2] != 0x80) || (data_in[3] != 0x01)) { printf("libdts: DTS Sync bad\n"); return; } audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); audio_buffer->frame_header_count = buf->decoder_info[1]; /* Number of frames */ audio_buffer->first_access_unit = buf->decoder_info[2]; /* First access unit */ #ifdef LOG_DEBUG printf("libdts: DTS frame_header_count = %u\n",audio_buffer->frame_header_count); printf("libdts: DTS first access unit = %u\n",audio_buffer->first_access_unit); #endif if (n == first_access_unit) { audio_buffer->vpts = buf->pts; } else { audio_buffer->vpts = 0; } data_out=(uint8_t *) audio_buffer->mem; ac5_pcm_samples=((data_in[4] & 0x01) << 6) | ((data_in[5] >>2) & 0x3f); ac5_length=((data_in[5] & 0x03) << 12) | (data_in[6] << 4) | ((data_in[7] & 0xf0) >> 4); ac5_length++; if (ac5_length > 8191) { printf("libdts: ac5_length too long\n"); ac5_pcm_length = 0; } else { ac5_pcm_length = (ac5_pcm_samples + 1) * 32; } switch (ac5_pcm_length) { case 512: ac5_spdif_type = 0x0b; /* DTS-1 (512-sample bursts) */ break; case 1024: ac5_spdif_type = 0x0c; /* DTS-1 (1024-sample bursts) */ break; case 2048: ac5_spdif_type = 0x0d; /* DTS-1 (2048-sample bursts) */ break; default: printf("libdts: DTS %i-sample bursts not supported\n", ac5_pcm_length); return; } #ifdef LOG_DEBUG { int i; printf("libdts: DTS frame type=%d\n",data_in[4] >> 7); printf("libdts: DTS deficit frame count=%d\n",(data_in[4] & 0x7f) >> 2); printf("libdts: DTS AC5 PCM samples=%d\n",ac5_pcm_samples); printf("libdts: DTS AC5 length=%d\n",ac5_length); printf("libdts: DTS AC5 bitrate=%d\n",((data_in[8] & 0x03) << 4) | (data_in[8] >> 4)); printf("libdts: DTS AC5 spdif type=%d\n", ac5_spdif_type); printf("libdts: "); for(i=2000;i<2048;i++) { printf("%02x ",data_in[i]); } printf("\n"); } #endif #ifdef LOG_DEBUG printf("libdts: DTS length=%d loop=%d pts=%lld\n",ac5_pcm_length,n,audio_buffer->vpts); #endif audio_buffer->num_frames = ac5_pcm_length; data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */ data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */ data_out[4] = ac5_spdif_type; /* DTS data */ data_out[5] = 0; /* Unknown */ data_out[6] = (ac5_length << 3) & 0xff; /* ac5_length * 8 */ data_out[7] = ((ac5_length ) >> 5) & 0xff; if( ac5_pcm_length ) { if( ac5_pcm_length % 2) { swab(data_in, &data_out[8], ac5_length ); } else { swab(data_in, &data_out[8], ac5_length + 1); } } this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); } } static void dts_dispose (audio_decoder_t *this_gen) { dts_decoder_t *this = (dts_decoder_t *) this_gen; if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); this->output_open = 0; free (this); } static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { dts_decoder_t *this ; #ifdef LOG_DEBUG printf("libdts: DTS open_plugin called.\n"); #endif this = (dts_decoder_t *) malloc (sizeof (dts_decoder_t)); this->audio_decoder.decode_data = dts_decode_data; this->audio_decoder.reset = dts_reset; this->audio_decoder.discontinuity = dts_discontinuity; this->audio_decoder.dispose = dts_dispose; this->stream = stream; this->class = class_gen; this->output_open = 0; this->rate = 48000; this->bits_per_sample=16; this->number_of_channels=2; return &this->audio_decoder; } static char *get_identifier (audio_decoder_class_t *this) { return "DTS"; } static char *get_description (audio_decoder_class_t *this) { return "DTS passthru audio format decoder plugin"; } static void dispose_class (audio_decoder_class_t *this) { #ifdef LOG_DEBUG printf("libdts: DTS class dispose called.\n"); #endif free (this); } static void *init_plugin (xine_t *xine, void *data) { dts_class_t *this ; #ifdef LOG_DEBUG printf("DTS class init_plugin called.\n"); #endif this = (dts_class_t *) malloc (sizeof (dts_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; this->decoder_class.get_description = get_description; this->decoder_class.dispose = dispose_class; return this; } static uint32_t audio_types[] = { BUF_AUDIO_DTS, 0 }; static decoder_info_t dec_info_audio = { audio_types, /* supported types */ 1 /* priority */ }; plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_DECODER, 13, "dts", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } };