eo301@0: #include "MP4Movies.h" eo301@0: #include "MP4LinkedList.h" eo301@0: #include "MP4InputStream.h" eo301@0: #include "IM_AF_Decoder.h" eo301@0: eo301@0: #ifndef BAILWITHERROR eo301@0: #define BAILWITHERROR(v) \ eo301@0: { \ eo301@0: err = (v); \ eo301@0: goto bail; \ eo301@0: } eo301@0: #endif eo301@0: eo301@0: typedef struct IMAFDecoder eo301@0: { eo301@0: u8 *InputMafFilename; eo301@0: FILE *InputFp; eo301@0: u32 TrackCount; eo301@0: // u32 CompletedTrackCount; eo301@0: u32 HasTimedTextTrack; eo301@0: eo301@0: MP4Movie moov; eo301@0: MP4Track trak; eo301@0: MP4Media media; eo301@0: u32 MovieTimescale; eo301@0: u32 MovieDuration; eo301@0: eo301@0: // Multi audio track eo301@0: MP4LinkedList TrackReaderList; // for all Track eo301@0: MP4LinkedList TrackSampleList; // for all Track Sample eo301@0: eo301@0: MP4TrackReader TimedTextTrackReader; eo301@0: MP4Handle TimedTextSampleH; eo301@0: MP4Handle TextH; eo301@0: u32 TimedTextTrackIndex; eo301@0: TextSampleStyleParam *TextParam; eo301@0: eo301@0: unsigned int HasSaocTrack; eo301@0: }IMAFDecoder; eo301@0: eo301@0: void InitTextSampleStyleParam(TextSampleStyleParam *TextParam) eo301@0: { eo301@0: if(TextParam) eo301@0: { eo301@0: if(TextParam->styl_text_styles) eo301@0: free(TextParam->styl_text_styles); eo301@0: if(TextParam->krok_highlight_end_time) eo301@0: free(TextParam->krok_highlight_end_time); eo301@0: if(TextParam->krok_startcharoffset) eo301@0: free(TextParam->krok_startcharoffset); eo301@0: if(TextParam->krok_endcharoffset) eo301@0: free(TextParam->krok_endcharoffset); eo301@0: if(TextParam->font) eo301@0: free(TextParam->font); eo301@0: memset(TextParam, 0, sizeof(TextSampleStyleParam)); eo301@0: } eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_Create(IMAF_DecoderH *IMafDecoder, IMAF_Decoder_Param *param) eo301@0: { eo301@0: IMAFDecoder *decoder = NULL; eo301@0: MP4Err err; eo301@0: u32 i; eo301@0: u32 sample_desc_type; eo301@0: MP4TrackReader reader; eo301@0: MP4Handle sampleH; eo301@0: u32 minorVersion; eo301@0: eo301@0: decoder = calloc(1, sizeof(IMAFDecoder)); eo301@0: eo301@0: if(param == NULL || param->InputMafFilename == NULL) eo301@0: { eo301@0: err = MP4BadParamErr; eo301@0: goto bail; eo301@0: } eo301@0: else eo301@0: decoder->InputMafFilename = _strdup(param->InputMafFilename); eo301@0: eo301@0: err = MP4OpenMovieFile( &decoder->moov, decoder->InputMafFilename, MP4OpenMovieInPlace ); if (err) goto bail; eo301@0: err = MP4GetMovieTrackCount( decoder->moov, &decoder->TrackCount); if(err) goto bail; eo301@0: eo301@0: //Timed Text eo301@0: for(i=0; iTrackCount; i++) eo301@0: { eo301@0: err = MP4GetMovieIndTrack( decoder->moov, i+1, &decoder->trak ); if (err) goto bail; eo301@0: err = MP4GetTrackMedia( decoder->trak, &decoder->media ); if (err) goto bail; eo301@0: err = MP4GetMediaSampleDescriptionType(decoder->media, &sample_desc_type); if(err) goto bail; eo301@0: if(sample_desc_type == 'tx3g') eo301@0: { eo301@0: decoder->HasTimedTextTrack = 1; eo301@0: decoder->TimedTextTrackIndex = i; eo301@0: break; eo301@0: } eo301@0: } eo301@0: eo301@0: param->HasTimedTextTrack = decoder->HasTimedTextTrack; eo301@0: param->NumberOfAudioTrack = decoder->TrackCount - decoder->HasTimedTextTrack; eo301@0: eo301@0: err = MP4GetMovieTimeScale(decoder->moov, &decoder->MovieTimescale); if(err) goto bail; eo301@0: param->MovieTimescale = decoder->MovieTimescale; eo301@0: eo301@0: err = MP4GetMovieDuration(decoder->moov, (u64*)&decoder->MovieDuration); if(err) goto bail; eo301@0: param->MovieDuration = decoder->MovieDuration; eo301@0: eo301@0: // Create TrackReader for all Track eo301@0: err = MP4MakeLinkedList( &decoder->TrackReaderList); if(err) goto bail; eo301@0: err = MP4MakeLinkedList( &decoder->TrackSampleList); if(err) goto bail; eo301@0: for(i=0; iTrackCount; i++) eo301@0: { eo301@0: err = MP4GetMovieIndTrack( decoder->moov, i+1, &decoder->trak ); if (err) goto bail; eo301@0: if(decoder->HasTimedTextTrack && decoder->TimedTextTrackIndex == i) eo301@0: { eo301@0: err = MP4CreateTrackReader( decoder->trak, &reader ); if (err) goto bail; eo301@0: decoder->TimedTextTrackReader = reader; eo301@0: } eo301@0: else eo301@0: { eo301@0: err = MP4CreateTrackReader( decoder->trak, &reader ); if (err) goto bail; eo301@0: err = MP4AddListEntry( reader, decoder->TrackReaderList); if (err) goto bail; eo301@0: eo301@0: err = MP4NewHandle(0, &sampleH); if(err) goto bail; eo301@0: err = MP4AddListEntry( sampleH, decoder->TrackSampleList); if (err) goto bail; eo301@0: } eo301@0: } eo301@0: eo301@0: err = MP4NewHandle(0, &decoder->TimedTextSampleH); if(err) goto bail; eo301@0: err = MP4NewHandle(0, &decoder->TextH); if(err) goto bail; eo301@0: eo301@0: decoder->TextParam = calloc(1, sizeof(TextSampleStyleParam)); eo301@0: eo301@0: err = ISOGetMovieBrand(decoder->moov, ¶m->MajorBrand, &minorVersion); if(err) goto bail; eo301@0: err = ISOGetNbCompatableBrands(decoder->moov, ¶m->NumberOfCompatibleBrands); if(err) goto bail; eo301@0: if(param->NumberOfCompatibleBrands) eo301@0: { eo301@0: param->CompatibleBrands = calloc(param->NumberOfCompatibleBrands, sizeof(u32)); eo301@0: err = ISOGetCompatableBrands(decoder->moov, param->CompatibleBrands); if(err) goto bail; eo301@0: } eo301@0: else eo301@0: param->CompatibleBrands = NULL; eo301@0: eo301@0: eo301@0: *IMafDecoder = decoder; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetAudioTrackInfos(IMAF_DecoderH IMafDecoder, unsigned int *AudioTrackObjectTypeArray eo301@0: ,unsigned int *AudioTrackIdArray, IMAF_AudioParam *AudioParamArray) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: u32 i; eo301@0: u32 outObjectType, sample_desc_type; eo301@0: u32 hasTimedText = 0; eo301@0: u32 trackID; eo301@0: unsigned int nBitsPerSample; eo301@0: unsigned int nChannels; eo301@0: unsigned int nSamplingFrequency; eo301@0: for(i=0; iTrackCount - decoder->HasTimedTextTrack; i++) eo301@0: { eo301@0: err = MP4GetMovieIndTrack( decoder->moov, i+1, &decoder->trak ); if (err) goto bail; eo301@0: err = MP4GetTrackMedia( decoder->trak, &decoder->media ); if (err) goto bail; eo301@0: err = MP4GetMediaSampleDescriptionType(decoder->media, &sample_desc_type); if(err) goto bail; eo301@0: if(sample_desc_type == 'mp4a') eo301@0: { eo301@0: err = MP4GetTrackID(decoder->trak, &trackID); if(err) goto bail; eo301@0: AudioTrackIdArray[i - hasTimedText] = trackID; eo301@0: err = MP4GetMediaDecoderType( decoder->media, 1, &outObjectType, NULL, NULL, NULL ); if(err) goto bail; eo301@0: if(outObjectType == AUDIO_OBJECT_TYPE_INDICATION_MP3 || outObjectType == AUDIO_OBJECT_TYPE_INDICATION_AAC eo301@0: || outObjectType == AUDIO_OBJECT_TYPE_INDICATION_SAOC|| outObjectType == AUDIO_OBJECT_TYPE_INDICATION_PCM) eo301@0: { eo301@0: AudioTrackObjectTypeArray[i - hasTimedText] = outObjectType; eo301@0: if(outObjectType = AUDIO_OBJECT_TYPE_INDICATION_SAOC) eo301@0: decoder->HasSaocTrack = 1; eo301@0: } eo301@0: else eo301@0: BAILWITHERROR(MP4BadDataErr) eo301@0: eo301@0: err = MP4GetSampleRateChannelBitsPerSample(decoder->media, &nSamplingFrequency, &nChannels, &nBitsPerSample); if(err) goto bail; eo301@0: AudioParamArray[i].nSamplingFrequency = nSamplingFrequency; eo301@0: AudioParamArray[i].nChannels = nChannels; eo301@0: AudioParamArray[i].nBitsPerSample = nBitsPerSample; eo301@0: } eo301@0: else eo301@0: { eo301@0: hasTimedText = 1; eo301@0: } eo301@0: } eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetGroupContainerInfo(IMAF_DecoderH IMafDecoder, unsigned int *GroupCount) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: err = MP4GetGroupContainerInfo(decoder->moov, GroupCount); if(err) goto bail; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetGroupByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_Group *grup) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: unsigned int *element_ID; eo301@0: char *group_name; eo301@0: char *group_description; eo301@0: eo301@0: err = MP4GetGroupByIndex(decoder->moov, i, eo301@0: &grup->group_ID, eo301@0: &grup->num_elements, eo301@0: &element_ID, eo301@0: &grup->group_activation_mode, eo301@0: &grup->group_activation_elements_number, eo301@0: &grup->group_reference_volume, eo301@0: &group_name, eo301@0: &group_description); if(err) goto bail; eo301@0: eo301@0: grup->element_ID =(u32*) calloc( grup->num_elements, sizeof(u32) ); eo301@0: memcpy(grup->element_ID, element_ID, sizeof(u32)*grup->num_elements); eo301@0: if(group_name) eo301@0: grup->group_name = _strdup(group_name); eo301@0: else eo301@0: grup->group_name = NULL; eo301@0: if(group_description) eo301@0: grup->group_description = _strdup(group_description); eo301@0: else eo301@0: grup->group_description = NULL; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetPresetContainerInfo(IMAF_DecoderH IMafDecoder, unsigned int *num_preset, unsigned int *default_preset_ID) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: err = MP4GetPresetContainerInfo(decoder->moov, num_preset, default_preset_ID); if(err) goto bail; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetPresetByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_Preset *prst) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: u32 *preset_element_ID; eo301@0: u32 *preset_volume_element; eo301@0: u32 *num_input_channel; eo301@0: u32 *updated_sample_number; eo301@0: char *preset_name; eo301@0: u32 ii; eo301@0: u32 element_count; eo301@0: eo301@0: err = MP4GetPresetByIndex(decoder->moov, i, eo301@0: &prst->preset_ID, eo301@0: &prst->num_preset_elements, eo301@0: &preset_element_ID, eo301@0: &prst->preset_type, eo301@0: &prst->preset_global_volume, eo301@0: &preset_volume_element, eo301@0: &num_input_channel , eo301@0: &prst->output_channel_type , eo301@0: &prst->num_output_channel , eo301@0: &prst->num_updates , eo301@0: &updated_sample_number, eo301@0: &preset_name); if(err) goto bail; eo301@0: eo301@0: prst->preset_element_ID =(u32*) calloc( prst->num_preset_elements, sizeof(u32) ); eo301@0: memcpy(prst->preset_element_ID, preset_element_ID, sizeof(u32)*prst->num_preset_elements); eo301@0: if(prst->preset_type == 0) eo301@0: { eo301@0: element_count = prst->num_preset_elements; eo301@0: prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); eo301@0: for(ii=0; iipreset_volume_element[ii] = preset_volume_element[ii]*2; eo301@0: } eo301@0: else if(prst->preset_type == 1) eo301@0: { eo301@0: element_count = prst->num_preset_elements*num_input_channel[0]*prst->num_output_channel; eo301@0: prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); eo301@0: for(ii=0; iipreset_volume_element[ii] = preset_volume_element[ii]*2; eo301@0: } eo301@0: else if(prst->preset_type == 2) eo301@0: { eo301@0: element_count = prst->num_preset_elements * prst->num_updates; eo301@0: prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); eo301@0: for(ii=0; iipreset_volume_element[ii] = preset_volume_element[ii]*2; eo301@0: } eo301@0: else if(prst->preset_type == 3) eo301@0: { eo301@0: element_count = prst->num_updates*prst->num_preset_elements*num_input_channel[0]*prst->num_output_channel; eo301@0: prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); eo301@0: for(ii=0; iipreset_volume_element[ii] = preset_volume_element[ii]*2; eo301@0: } eo301@0: eo301@0: if(num_input_channel) eo301@0: { eo301@0: prst->num_input_channel =(u32*) calloc( prst->num_preset_elements, sizeof(u32) ); eo301@0: memcpy(prst->num_input_channel, num_input_channel, sizeof(u32)*prst->num_preset_elements); eo301@0: } eo301@0: else eo301@0: prst->num_input_channel = NULL; eo301@0: if(updated_sample_number) eo301@0: { eo301@0: prst->updated_sample_number =(u32*) calloc( prst->num_updates, sizeof(u32) ); eo301@0: memcpy(prst->updated_sample_number, updated_sample_number, sizeof(u32)*prst->num_updates); eo301@0: } eo301@0: else eo301@0: prst->updated_sample_number = NULL; eo301@0: if(preset_name) eo301@0: prst->preset_name = _strdup(preset_name); eo301@0: else eo301@0: prst->preset_name = NULL; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetRuleContainerInfo(IMAF_DecoderH IMafDecoder, unsigned int *num_selection_rules, unsigned int *num_mixing_rules) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: err = MP4GetRuleContainerInfo(decoder->moov, num_selection_rules, num_mixing_rules); if(err) goto bail; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetSelectionRuleByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_SelectionRule *rusc) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: char *selection_rule_description; eo301@0: err = MP4GetSelectionRuleByIndex(decoder->moov, i, eo301@0: &rusc->selection_rule_ID, eo301@0: &rusc->selection_rule_type, eo301@0: &rusc->element_ID, eo301@0: &rusc->min_num_elements, eo301@0: &rusc->max_num_elements, eo301@0: &rusc->key_element_ID, eo301@0: &selection_rule_description); if(err) goto bail; eo301@0: eo301@0: if(selection_rule_description) eo301@0: rusc->selection_rule_description = _strdup(selection_rule_description); eo301@0: else eo301@0: rusc->selection_rule_description = NULL; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetMixingRuleByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_MixingRule *rumx) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: char *mixing_rule_description; eo301@0: err = MP4GetMixingRuleByIndex(decoder->moov, i, eo301@0: &rumx->mixing_rule_ID, eo301@0: &rumx->mixing_rule_type, eo301@0: &rumx->element_ID, eo301@0: &rumx->min_volume, eo301@0: &rumx->max_volume, eo301@0: &rumx->key_element_ID, eo301@0: &mixing_rule_description); if(err) goto bail; eo301@0: eo301@0: if(mixing_rule_description) eo301@0: rumx->mixing_rule_description = _strdup(mixing_rule_description); eo301@0: else eo301@0: rumx->mixing_rule_description = NULL; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAFDecoder_SeekSample(IMAF_DecoderH IMafDecoder, unsigned int mediaTime) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: u32 timescale, i; eo301@0: MP4TrackReader reader; eo301@0: eo301@0: err = MP4GetMediaTimeScale(decoder->media, ×cale); if(err) goto bail; eo301@0: mediaTime /= 1000; //in miliseconds eo301@0: mediaTime *= timescale; eo301@0: eo301@0: for(i=0; iTrackCount - decoder->HasTimedTextTrack; i++) eo301@0: { eo301@0: err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; eo301@0: err = MP4TrackReaderSeekToSyncSample( reader, mediaTime); if(err) goto bail; eo301@0: } eo301@0: if(decoder->TimedTextTrackReader) eo301@0: { eo301@0: err = MP4TrackReaderSeekToSyncSample( decoder->TimedTextTrackReader, mediaTime); if(err) goto bail; eo301@0: } eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAFDecoder_GetNextAudioSampleByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, eo301@0: unsigned char **SampleData, unsigned int *SampleDataSize, unsigned int *CurrentTime, unsigned int *sampleNumber) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: MP4TrackReader reader; eo301@0: MP4Handle sampleH; eo301@0: u32 unitSize; eo301@0: u32 sampleFlags; eo301@0: u32 cts; eo301@0: u32 dts; eo301@0: eo301@0: if(i >= decoder->TrackCount - decoder->HasTimedTextTrack) eo301@0: BAILWITHERROR(MP4BadParamErr) eo301@0: err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; eo301@0: err = MP4GetListEntry(decoder->TrackSampleList, i, (char**)&sampleH); if(err) goto bail; eo301@0: err = MP4TrackReaderGetNextAccessUnitWithSampleNumber( reader, sampleH, &unitSize,&sampleFlags, &cts, &dts, sampleNumber); eo301@0: eo301@0: if ( err ) eo301@0: { eo301@0: if ( err == MP4EOF ) eo301@0: { eo301@0: *SampleData = NULL; eo301@0: *SampleDataSize = 0; eo301@0: *CurrentTime = 0; eo301@0: err = MP4NoErr; eo301@0: } eo301@0: else eo301@0: goto bail; eo301@0: } eo301@0: eo301@0: *CurrentTime = dts; eo301@0: *SampleData = *sampleH; eo301@0: *SampleDataSize = unitSize; eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAFDecoder_GetNextTextSample(IMAF_DecoderH IMafDecoder, eo301@0: unsigned char **SampleData, unsigned int *SampleDataSize, unsigned int *CurrentTime, TextSampleStyleParam **param) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: u32 unitSize; eo301@0: u32 sampleFlags; eo301@0: u32 cts; eo301@0: u32 dts; eo301@0: u32 i; eo301@0: u8 *TextSample; eo301@0: MP4InputStreamPtr is; eo301@0: u32 TextModifiersSize, TotalAtomSize; eo301@0: MP4AtomPtr entry; eo301@0: TextStyleAtomPtr styl; eo301@0: TextHighlightAtomPtr hlit; eo301@0: TextHighlightColorAtomPtr hclr; eo301@0: TextKaraokeAtomPtr krok; eo301@0: TextSampleEntryValue tx3g_value; eo301@0: eo301@0: eo301@0: err = MP4TrackReaderGetNextAccessUnit(decoder->TimedTextTrackReader, decoder->TimedTextSampleH, &unitSize, &sampleFlags, &cts, &dts); eo301@0: eo301@0: if ( err ) eo301@0: { eo301@0: if ( err == MP4EOF ) eo301@0: { eo301@0: *SampleData = NULL; eo301@0: *SampleDataSize = 0; eo301@0: *CurrentTime = 0; eo301@0: return MP4EOF; eo301@0: } eo301@0: else eo301@0: goto bail; eo301@0: } eo301@0: eo301@0: err = MP4TrackReaderGetTextSampleEntryValues(decoder->TimedTextTrackReader, &tx3g_value); if(err) goto bail; eo301@0: eo301@0: #if 0 //only text eo301@0: *CurrentTime = dts; eo301@0: *SampleData = *decoder->TimedTextSampleH; eo301@0: *SampleDataSize = unitSize; eo301@0: #else eo301@0: *CurrentTime = dts; eo301@0: TextSample = *decoder->TimedTextSampleH; eo301@0: *SampleDataSize = TextSample[0]<<8 | TextSample[1]; eo301@0: TextSample+=2; eo301@0: MP4SetHandleSize(decoder->TextH, *SampleDataSize+1); eo301@0: memcpy(*decoder->TextH, TextSample, *SampleDataSize); eo301@0: TextSample += *SampleDataSize; eo301@0: (*decoder->TextH)[*SampleDataSize] = '\0'; eo301@0: *SampleData = *decoder->TextH; eo301@0: eo301@0: //Extract Text Style eo301@0: InitTextSampleStyleParam(decoder->TextParam); eo301@0: decoder->TextParam->displayFlags= tx3g_value.displayFlags; eo301@0: decoder->TextParam->horizontal_justification= tx3g_value.horizontal_justification; eo301@0: decoder->TextParam->vertical_justification= tx3g_value.vertical_justification; eo301@0: decoder->TextParam->background_color_r= tx3g_value.background_color_r; eo301@0: decoder->TextParam->background_color_g= tx3g_value.background_color_g; eo301@0: decoder->TextParam->background_color_b= tx3g_value.background_color_b; eo301@0: decoder->TextParam->background_color_a= tx3g_value.background_color_a; eo301@0: decoder->TextParam->default_text_box_top= tx3g_value.default_text_box_top; eo301@0: decoder->TextParam->default_text_box_left= tx3g_value.default_text_box_left; eo301@0: decoder->TextParam->default_text_box_bottom= tx3g_value.default_text_box_bottom; eo301@0: decoder->TextParam->default_text_box_right= tx3g_value.default_text_box_right; eo301@0: decoder->TextParam->default_style_startChar= tx3g_value.default_style_startChar; eo301@0: decoder->TextParam->default_style_endChar= tx3g_value.default_style_endChar; eo301@0: decoder->TextParam->default_style_font_ID= tx3g_value.default_style_font_ID; eo301@0: decoder->TextParam->default_style_face_style_flags= tx3g_value.default_style_face_style_flags; eo301@0: decoder->TextParam->default_style_font_size= tx3g_value.default_style_font_size; eo301@0: decoder->TextParam->default_style_text_color_r= tx3g_value.default_style_text_color_r; eo301@0: decoder->TextParam->default_style_text_color_g= tx3g_value.default_style_text_color_g; eo301@0: decoder->TextParam->default_style_text_color_b= tx3g_value.default_style_text_color_b; eo301@0: decoder->TextParam->default_style_text_color_a= tx3g_value.default_style_text_color_a; eo301@0: decoder->TextParam->font_ID= tx3g_value.font_ID; eo301@0: decoder->TextParam->font_name_length= tx3g_value.font_name_length; eo301@0: decoder->TextParam->font= _strdup(tx3g_value.font); eo301@0: free(tx3g_value.font); eo301@0: eo301@0: TotalAtomSize= 0; eo301@0: TextModifiersSize = unitSize - 2 - *SampleDataSize; eo301@0: err = MP4CreateMemoryInputStream(TextSample, TextModifiersSize, &is ); if (err) goto bail; eo301@0: is->debugging = 0; eo301@0: while(TextModifiersSize>TotalAtomSize) eo301@0: { eo301@0: err = MP4ParseAtom( is, &entry ); if (err) goto bail; eo301@0: TotalAtomSize += entry->size; eo301@0: if(entry->type == 'styl') eo301@0: { eo301@0: StyleRecordStructPtr styleRecord; eo301@0: styl = (TextStyleAtomPtr)entry; eo301@0: decoder->TextParam->styl_entry_count = styl->entry_count; eo301@0: decoder->TextParam->styl_text_styles = (StyleRecord*)calloc(styl->entry_count, sizeof(styleRecord)); eo301@0: for(i=0; ientry_count; i++) eo301@0: { eo301@0: err = MP4GetListEntry(styl->styleRecordList, i, (char**)&styleRecord); if(err) goto bail; eo301@0: memcpy(&decoder->TextParam->styl_text_styles[i], styleRecord, sizeof(StyleRecord)); eo301@0: } eo301@0: } eo301@0: else if(entry->type == 'hlit') eo301@0: { eo301@0: hlit = (TextHighlightAtomPtr)entry; eo301@0: decoder->TextParam->hlit_startcharoffset = hlit->startcharoffset; eo301@0: decoder->TextParam->hlit_endcharoffset = hlit->endcharoffset; eo301@0: } eo301@0: else if(entry->type == 'hclr') eo301@0: { eo301@0: hclr = (TextHighlightColorAtomPtr)entry; eo301@0: decoder->TextParam->hclr_highlight_color_r = hclr->highlight_color_r; eo301@0: decoder->TextParam->hclr_highlight_color_g = hclr->highlight_color_g; eo301@0: decoder->TextParam->hclr_highlight_color_b = hclr->highlight_color_b; eo301@0: decoder->TextParam->hclr_highlight_color_a = hclr->highlight_color_a; eo301@0: } eo301@0: else if(entry->type == 'krok') eo301@0: { eo301@0: krok = (TextKaraokeAtomPtr)entry; eo301@0: decoder->TextParam->krok_highlight_start_time = krok->highlight_start_time; eo301@0: decoder->TextParam->krok_entry_count = krok->entry_count; eo301@0: decoder->TextParam->krok_highlight_end_time = calloc(krok->entry_count, sizeof(u32)); eo301@0: decoder->TextParam->krok_startcharoffset= calloc(krok->entry_count, sizeof(u32)); eo301@0: decoder->TextParam->krok_endcharoffset = calloc(krok->entry_count, sizeof(u32)); eo301@0: for(i=0; ientry_count; i++) eo301@0: { eo301@0: decoder->TextParam->krok_highlight_end_time[i] =krok->highlight_end_time[i]; eo301@0: decoder->TextParam->krok_startcharoffset[i] = krok->startcharoffset[i]; eo301@0: decoder->TextParam->krok_endcharoffset[i] = krok->endcharoffset[i]; eo301@0: } eo301@0: } eo301@0: else eo301@0: { eo301@0: BAILWITHERROR(MP4NotImplementedErr) eo301@0: } eo301@0: eo301@0: entry->destroy(entry); eo301@0: } eo301@0: eo301@0: if (is) { eo301@0: is->destroy( is ); eo301@0: is = NULL; eo301@0: } eo301@0: eo301@0: *param = decoder->TextParam; eo301@0: #endif eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAFDecoder_GetDsiByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, char** dsi, unsigned int *dsiSize) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: MP4TrackReader reader; eo301@0: MP4Handle specificInfoH; eo301@0: eo301@0: err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; eo301@0: eo301@0: err = MP4NewHandle(0, &specificInfoH); if(err) goto bail; eo301@0: err = MP4TrackReaderGetCurrentDecoderSpecificInfo(reader, specificInfoH); if(err) goto bail; eo301@0: err = MP4GetHandleSize(specificInfoH, dsiSize); eo301@0: *dsi = (u8*)malloc(*dsiSize); eo301@0: memcpy(*dsi, *specificInfoH, *dsiSize); eo301@0: err = MP4DisposeHandle(specificInfoH); if(err) goto bail; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAFDecoder_GetSongImage(IMAF_DecoderH IMafDecoder, unsigned char **image, unsigned int *imageSize) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: u8 *content_type; eo301@0: eo301@0: err = MP4GetMovieIndTrack( decoder->moov, 1, &decoder->trak ); if (err) goto bail; eo301@0: err = MP4GetTrackMedia( decoder->trak, &decoder->media ); if (err) goto bail; eo301@0: err = MP4_GetImageByItemId(decoder->moov, decoder->media, image, imageSize, &content_type, 1); if(err) goto bail; eo301@0: eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAFDecoder_GetMetadata(IMAF_DecoderH IMafDecoder, unsigned char **Meta, unsigned int *MetaSize) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: err = MP4GetMetaXml(decoder->moov, Meta, MetaSize); if(err) goto bail; eo301@0: bail: eo301@0: TEST_RETURN( err ); eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API IMAF_Err IMAF_Decoder_Destroy(IMAF_DecoderH IMafDecoder) eo301@0: { eo301@0: IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; eo301@0: IMAF_Err err; eo301@0: eo301@0: if(decoder) eo301@0: { eo301@0: if(decoder->InputMafFilename) eo301@0: { eo301@0: free(decoder->InputMafFilename); eo301@0: decoder->InputMafFilename = NULL; eo301@0: } eo301@0: eo301@0: if(decoder->TrackReaderList) eo301@0: { eo301@0: u32 i; eo301@0: MP4TrackReader reader; eo301@0: MP4Handle sampleH; eo301@0: for(i=0; iTrackCount - decoder->HasTimedTextTrack; i++) eo301@0: { eo301@0: err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; eo301@0: err = MP4DisposeTrackReader(reader); if(err) goto bail; eo301@0: err = MP4GetListEntry(decoder->TrackSampleList, i, (char**)&sampleH); if(err) goto bail; eo301@0: err = MP4DisposeHandle(sampleH); if(err) goto bail; eo301@0: } eo301@0: err = MP4DeleteLinkedList(decoder->TrackReaderList); if(err) goto bail; eo301@0: err = MP4DeleteLinkedList(decoder->TrackSampleList); if(err) goto bail; eo301@0: decoder->TrackReaderList = NULL; eo301@0: decoder->TrackSampleList = NULL; eo301@0: } eo301@0: eo301@0: if(decoder->TimedTextSampleH) eo301@0: MP4DisposeHandle(decoder->TimedTextSampleH); eo301@0: if(decoder->TextH) eo301@0: MP4DisposeHandle(decoder->TextH); eo301@0: if(decoder->TimedTextTrackReader) eo301@0: MP4DisposeTrackReader(decoder->TimedTextTrackReader); eo301@0: if(decoder->TextParam) eo301@0: { eo301@0: InitTextSampleStyleParam(decoder->TextParam); eo301@0: free(decoder->TextParam); eo301@0: } eo301@0: eo301@0: if(decoder->moov) eo301@0: { eo301@0: err = MP4DisposeMovie( decoder->moov ); if(err) goto bail; eo301@0: } eo301@0: free(decoder); eo301@0: } eo301@0: eo301@0: bail: eo301@0: return err; eo301@0: } eo301@0: eo301@0: IMAF_DECODER_API char* IMAF_Decoder_GetLastError(IMAF_Err err) eo301@0: { eo301@0: return MP4GetLastError(err); eo301@0: }