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