Mercurial > hg > enc-imaf
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:138a3cea9792 |
---|---|
1 #include "MP4Movies.h" | |
2 #include "MP4LinkedList.h" | |
3 #include "MP4InputStream.h" | |
4 #include "IM_AF_Decoder.h" | |
5 | |
6 #ifndef BAILWITHERROR | |
7 #define BAILWITHERROR(v) \ | |
8 { \ | |
9 err = (v); \ | |
10 goto bail; \ | |
11 } | |
12 #endif | |
13 | |
14 typedef struct IMAFDecoder | |
15 { | |
16 u8 *InputMafFilename; | |
17 FILE *InputFp; | |
18 u32 TrackCount; | |
19 // u32 CompletedTrackCount; | |
20 u32 HasTimedTextTrack; | |
21 | |
22 MP4Movie moov; | |
23 MP4Track trak; | |
24 MP4Media media; | |
25 u32 MovieTimescale; | |
26 u32 MovieDuration; | |
27 | |
28 // Multi audio track | |
29 MP4LinkedList TrackReaderList; // for all Track | |
30 MP4LinkedList TrackSampleList; // for all Track Sample | |
31 | |
32 MP4TrackReader TimedTextTrackReader; | |
33 MP4Handle TimedTextSampleH; | |
34 MP4Handle TextH; | |
35 u32 TimedTextTrackIndex; | |
36 TextSampleStyleParam *TextParam; | |
37 | |
38 unsigned int HasSaocTrack; | |
39 }IMAFDecoder; | |
40 | |
41 void InitTextSampleStyleParam(TextSampleStyleParam *TextParam) | |
42 { | |
43 if(TextParam) | |
44 { | |
45 if(TextParam->styl_text_styles) | |
46 free(TextParam->styl_text_styles); | |
47 if(TextParam->krok_highlight_end_time) | |
48 free(TextParam->krok_highlight_end_time); | |
49 if(TextParam->krok_startcharoffset) | |
50 free(TextParam->krok_startcharoffset); | |
51 if(TextParam->krok_endcharoffset) | |
52 free(TextParam->krok_endcharoffset); | |
53 if(TextParam->font) | |
54 free(TextParam->font); | |
55 memset(TextParam, 0, sizeof(TextSampleStyleParam)); | |
56 } | |
57 } | |
58 | |
59 IMAF_DECODER_API IMAF_Err IMAF_Decoder_Create(IMAF_DecoderH *IMafDecoder, IMAF_Decoder_Param *param) | |
60 { | |
61 IMAFDecoder *decoder = NULL; | |
62 MP4Err err; | |
63 u32 i; | |
64 u32 sample_desc_type; | |
65 MP4TrackReader reader; | |
66 MP4Handle sampleH; | |
67 u32 minorVersion; | |
68 | |
69 decoder = calloc(1, sizeof(IMAFDecoder)); | |
70 | |
71 if(param == NULL || param->InputMafFilename == NULL) | |
72 { | |
73 err = MP4BadParamErr; | |
74 goto bail; | |
75 } | |
76 else | |
77 decoder->InputMafFilename = _strdup(param->InputMafFilename); | |
78 | |
79 err = MP4OpenMovieFile( &decoder->moov, decoder->InputMafFilename, MP4OpenMovieInPlace ); if (err) goto bail; | |
80 err = MP4GetMovieTrackCount( decoder->moov, &decoder->TrackCount); if(err) goto bail; | |
81 | |
82 //Timed Text | |
83 for(i=0; i<decoder->TrackCount; i++) | |
84 { | |
85 err = MP4GetMovieIndTrack( decoder->moov, i+1, &decoder->trak ); if (err) goto bail; | |
86 err = MP4GetTrackMedia( decoder->trak, &decoder->media ); if (err) goto bail; | |
87 err = MP4GetMediaSampleDescriptionType(decoder->media, &sample_desc_type); if(err) goto bail; | |
88 if(sample_desc_type == 'tx3g') | |
89 { | |
90 decoder->HasTimedTextTrack = 1; | |
91 decoder->TimedTextTrackIndex = i; | |
92 break; | |
93 } | |
94 } | |
95 | |
96 param->HasTimedTextTrack = decoder->HasTimedTextTrack; | |
97 param->NumberOfAudioTrack = decoder->TrackCount - decoder->HasTimedTextTrack; | |
98 | |
99 err = MP4GetMovieTimeScale(decoder->moov, &decoder->MovieTimescale); if(err) goto bail; | |
100 param->MovieTimescale = decoder->MovieTimescale; | |
101 | |
102 err = MP4GetMovieDuration(decoder->moov, (u64*)&decoder->MovieDuration); if(err) goto bail; | |
103 param->MovieDuration = decoder->MovieDuration; | |
104 | |
105 // Create TrackReader for all Track | |
106 err = MP4MakeLinkedList( &decoder->TrackReaderList); if(err) goto bail; | |
107 err = MP4MakeLinkedList( &decoder->TrackSampleList); if(err) goto bail; | |
108 for(i=0; i<decoder->TrackCount; i++) | |
109 { | |
110 err = MP4GetMovieIndTrack( decoder->moov, i+1, &decoder->trak ); if (err) goto bail; | |
111 if(decoder->HasTimedTextTrack && decoder->TimedTextTrackIndex == i) | |
112 { | |
113 err = MP4CreateTrackReader( decoder->trak, &reader ); if (err) goto bail; | |
114 decoder->TimedTextTrackReader = reader; | |
115 } | |
116 else | |
117 { | |
118 err = MP4CreateTrackReader( decoder->trak, &reader ); if (err) goto bail; | |
119 err = MP4AddListEntry( reader, decoder->TrackReaderList); if (err) goto bail; | |
120 | |
121 err = MP4NewHandle(0, &sampleH); if(err) goto bail; | |
122 err = MP4AddListEntry( sampleH, decoder->TrackSampleList); if (err) goto bail; | |
123 } | |
124 } | |
125 | |
126 err = MP4NewHandle(0, &decoder->TimedTextSampleH); if(err) goto bail; | |
127 err = MP4NewHandle(0, &decoder->TextH); if(err) goto bail; | |
128 | |
129 decoder->TextParam = calloc(1, sizeof(TextSampleStyleParam)); | |
130 | |
131 err = ISOGetMovieBrand(decoder->moov, ¶m->MajorBrand, &minorVersion); if(err) goto bail; | |
132 err = ISOGetNbCompatableBrands(decoder->moov, ¶m->NumberOfCompatibleBrands); if(err) goto bail; | |
133 if(param->NumberOfCompatibleBrands) | |
134 { | |
135 param->CompatibleBrands = calloc(param->NumberOfCompatibleBrands, sizeof(u32)); | |
136 err = ISOGetCompatableBrands(decoder->moov, param->CompatibleBrands); if(err) goto bail; | |
137 } | |
138 else | |
139 param->CompatibleBrands = NULL; | |
140 | |
141 | |
142 *IMafDecoder = decoder; | |
143 | |
144 bail: | |
145 TEST_RETURN( err ); | |
146 return err; | |
147 } | |
148 | |
149 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetAudioTrackInfos(IMAF_DecoderH IMafDecoder, unsigned int *AudioTrackObjectTypeArray | |
150 ,unsigned int *AudioTrackIdArray, IMAF_AudioParam *AudioParamArray) | |
151 { | |
152 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
153 IMAF_Err err; | |
154 u32 i; | |
155 u32 outObjectType, sample_desc_type; | |
156 u32 hasTimedText = 0; | |
157 u32 trackID; | |
158 unsigned int nBitsPerSample; | |
159 unsigned int nChannels; | |
160 unsigned int nSamplingFrequency; | |
161 for(i=0; i<decoder->TrackCount - decoder->HasTimedTextTrack; i++) | |
162 { | |
163 err = MP4GetMovieIndTrack( decoder->moov, i+1, &decoder->trak ); if (err) goto bail; | |
164 err = MP4GetTrackMedia( decoder->trak, &decoder->media ); if (err) goto bail; | |
165 err = MP4GetMediaSampleDescriptionType(decoder->media, &sample_desc_type); if(err) goto bail; | |
166 if(sample_desc_type == 'mp4a') | |
167 { | |
168 err = MP4GetTrackID(decoder->trak, &trackID); if(err) goto bail; | |
169 AudioTrackIdArray[i - hasTimedText] = trackID; | |
170 err = MP4GetMediaDecoderType( decoder->media, 1, &outObjectType, NULL, NULL, NULL ); if(err) goto bail; | |
171 if(outObjectType == AUDIO_OBJECT_TYPE_INDICATION_MP3 || outObjectType == AUDIO_OBJECT_TYPE_INDICATION_AAC | |
172 || outObjectType == AUDIO_OBJECT_TYPE_INDICATION_SAOC|| outObjectType == AUDIO_OBJECT_TYPE_INDICATION_PCM) | |
173 { | |
174 AudioTrackObjectTypeArray[i - hasTimedText] = outObjectType; | |
175 if(outObjectType = AUDIO_OBJECT_TYPE_INDICATION_SAOC) | |
176 decoder->HasSaocTrack = 1; | |
177 } | |
178 else | |
179 BAILWITHERROR(MP4BadDataErr) | |
180 | |
181 err = MP4GetSampleRateChannelBitsPerSample(decoder->media, &nSamplingFrequency, &nChannels, &nBitsPerSample); if(err) goto bail; | |
182 AudioParamArray[i].nSamplingFrequency = nSamplingFrequency; | |
183 AudioParamArray[i].nChannels = nChannels; | |
184 AudioParamArray[i].nBitsPerSample = nBitsPerSample; | |
185 } | |
186 else | |
187 { | |
188 hasTimedText = 1; | |
189 } | |
190 } | |
191 | |
192 bail: | |
193 TEST_RETURN( err ); | |
194 return err; | |
195 } | |
196 | |
197 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetGroupContainerInfo(IMAF_DecoderH IMafDecoder, unsigned int *GroupCount) | |
198 { | |
199 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
200 IMAF_Err err; | |
201 | |
202 err = MP4GetGroupContainerInfo(decoder->moov, GroupCount); if(err) goto bail; | |
203 | |
204 bail: | |
205 TEST_RETURN( err ); | |
206 return err; | |
207 } | |
208 | |
209 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetGroupByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_Group *grup) | |
210 { | |
211 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
212 IMAF_Err err; | |
213 unsigned int *element_ID; | |
214 char *group_name; | |
215 char *group_description; | |
216 | |
217 err = MP4GetGroupByIndex(decoder->moov, i, | |
218 &grup->group_ID, | |
219 &grup->num_elements, | |
220 &element_ID, | |
221 &grup->group_activation_mode, | |
222 &grup->group_activation_elements_number, | |
223 &grup->group_reference_volume, | |
224 &group_name, | |
225 &group_description); if(err) goto bail; | |
226 | |
227 grup->element_ID =(u32*) calloc( grup->num_elements, sizeof(u32) ); | |
228 memcpy(grup->element_ID, element_ID, sizeof(u32)*grup->num_elements); | |
229 if(group_name) | |
230 grup->group_name = _strdup(group_name); | |
231 else | |
232 grup->group_name = NULL; | |
233 if(group_description) | |
234 grup->group_description = _strdup(group_description); | |
235 else | |
236 grup->group_description = NULL; | |
237 | |
238 bail: | |
239 TEST_RETURN( err ); | |
240 return err; | |
241 } | |
242 | |
243 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetPresetContainerInfo(IMAF_DecoderH IMafDecoder, unsigned int *num_preset, unsigned int *default_preset_ID) | |
244 { | |
245 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
246 IMAF_Err err; | |
247 | |
248 err = MP4GetPresetContainerInfo(decoder->moov, num_preset, default_preset_ID); if(err) goto bail; | |
249 | |
250 bail: | |
251 TEST_RETURN( err ); | |
252 return err; | |
253 } | |
254 | |
255 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetPresetByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_Preset *prst) | |
256 { | |
257 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
258 IMAF_Err err; | |
259 | |
260 u32 *preset_element_ID; | |
261 u32 *preset_volume_element; | |
262 u32 *num_input_channel; | |
263 u32 *updated_sample_number; | |
264 char *preset_name; | |
265 u32 ii; | |
266 u32 element_count; | |
267 | |
268 err = MP4GetPresetByIndex(decoder->moov, i, | |
269 &prst->preset_ID, | |
270 &prst->num_preset_elements, | |
271 &preset_element_ID, | |
272 &prst->preset_type, | |
273 &prst->preset_global_volume, | |
274 &preset_volume_element, | |
275 &num_input_channel , | |
276 &prst->output_channel_type , | |
277 &prst->num_output_channel , | |
278 &prst->num_updates , | |
279 &updated_sample_number, | |
280 &preset_name); if(err) goto bail; | |
281 | |
282 prst->preset_element_ID =(u32*) calloc( prst->num_preset_elements, sizeof(u32) ); | |
283 memcpy(prst->preset_element_ID, preset_element_ID, sizeof(u32)*prst->num_preset_elements); | |
284 if(prst->preset_type == 0) | |
285 { | |
286 element_count = prst->num_preset_elements; | |
287 prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); | |
288 for(ii=0; ii<element_count; ii++) | |
289 prst->preset_volume_element[ii] = preset_volume_element[ii]*2; | |
290 } | |
291 else if(prst->preset_type == 1) | |
292 { | |
293 element_count = prst->num_preset_elements*num_input_channel[0]*prst->num_output_channel; | |
294 prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); | |
295 for(ii=0; ii<element_count; ii++) | |
296 prst->preset_volume_element[ii] = preset_volume_element[ii]*2; | |
297 } | |
298 else if(prst->preset_type == 2) | |
299 { | |
300 element_count = prst->num_preset_elements * prst->num_updates; | |
301 prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); | |
302 for(ii=0; ii<element_count; ii++) | |
303 prst->preset_volume_element[ii] = preset_volume_element[ii]*2; | |
304 } | |
305 else if(prst->preset_type == 3) | |
306 { | |
307 element_count = prst->num_updates*prst->num_preset_elements*num_input_channel[0]*prst->num_output_channel; | |
308 prst->preset_volume_element =(u32*) calloc( element_count, sizeof(u32) ); | |
309 for(ii=0; ii<element_count; ii++) | |
310 prst->preset_volume_element[ii] = preset_volume_element[ii]*2; | |
311 } | |
312 | |
313 if(num_input_channel) | |
314 { | |
315 prst->num_input_channel =(u32*) calloc( prst->num_preset_elements, sizeof(u32) ); | |
316 memcpy(prst->num_input_channel, num_input_channel, sizeof(u32)*prst->num_preset_elements); | |
317 } | |
318 else | |
319 prst->num_input_channel = NULL; | |
320 if(updated_sample_number) | |
321 { | |
322 prst->updated_sample_number =(u32*) calloc( prst->num_updates, sizeof(u32) ); | |
323 memcpy(prst->updated_sample_number, updated_sample_number, sizeof(u32)*prst->num_updates); | |
324 } | |
325 else | |
326 prst->updated_sample_number = NULL; | |
327 if(preset_name) | |
328 prst->preset_name = _strdup(preset_name); | |
329 else | |
330 prst->preset_name = NULL; | |
331 | |
332 bail: | |
333 TEST_RETURN( err ); | |
334 return err; | |
335 } | |
336 | |
337 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetRuleContainerInfo(IMAF_DecoderH IMafDecoder, unsigned int *num_selection_rules, unsigned int *num_mixing_rules) | |
338 { | |
339 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
340 IMAF_Err err; | |
341 | |
342 err = MP4GetRuleContainerInfo(decoder->moov, num_selection_rules, num_mixing_rules); if(err) goto bail; | |
343 | |
344 bail: | |
345 TEST_RETURN( err ); | |
346 return err; | |
347 } | |
348 | |
349 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetSelectionRuleByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_SelectionRule *rusc) | |
350 { | |
351 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
352 IMAF_Err err; | |
353 | |
354 char *selection_rule_description; | |
355 err = MP4GetSelectionRuleByIndex(decoder->moov, i, | |
356 &rusc->selection_rule_ID, | |
357 &rusc->selection_rule_type, | |
358 &rusc->element_ID, | |
359 &rusc->min_num_elements, | |
360 &rusc->max_num_elements, | |
361 &rusc->key_element_ID, | |
362 &selection_rule_description); if(err) goto bail; | |
363 | |
364 if(selection_rule_description) | |
365 rusc->selection_rule_description = _strdup(selection_rule_description); | |
366 else | |
367 rusc->selection_rule_description = NULL; | |
368 | |
369 bail: | |
370 TEST_RETURN( err ); | |
371 return err; | |
372 } | |
373 | |
374 IMAF_DECODER_API IMAF_Err IMAF_Decoder_GetMixingRuleByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, IMAF_MixingRule *rumx) | |
375 { | |
376 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
377 IMAF_Err err; | |
378 | |
379 char *mixing_rule_description; | |
380 err = MP4GetMixingRuleByIndex(decoder->moov, i, | |
381 &rumx->mixing_rule_ID, | |
382 &rumx->mixing_rule_type, | |
383 &rumx->element_ID, | |
384 &rumx->min_volume, | |
385 &rumx->max_volume, | |
386 &rumx->key_element_ID, | |
387 &mixing_rule_description); if(err) goto bail; | |
388 | |
389 if(mixing_rule_description) | |
390 rumx->mixing_rule_description = _strdup(mixing_rule_description); | |
391 else | |
392 rumx->mixing_rule_description = NULL; | |
393 | |
394 bail: | |
395 TEST_RETURN( err ); | |
396 return err; | |
397 } | |
398 | |
399 IMAF_DECODER_API IMAF_Err IMAFDecoder_SeekSample(IMAF_DecoderH IMafDecoder, unsigned int mediaTime) | |
400 { | |
401 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
402 IMAF_Err err; | |
403 u32 timescale, i; | |
404 MP4TrackReader reader; | |
405 | |
406 err = MP4GetMediaTimeScale(decoder->media, ×cale); if(err) goto bail; | |
407 mediaTime /= 1000; //in miliseconds | |
408 mediaTime *= timescale; | |
409 | |
410 for(i=0; i<decoder->TrackCount - decoder->HasTimedTextTrack; i++) | |
411 { | |
412 err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; | |
413 err = MP4TrackReaderSeekToSyncSample( reader, mediaTime); if(err) goto bail; | |
414 } | |
415 if(decoder->TimedTextTrackReader) | |
416 { | |
417 err = MP4TrackReaderSeekToSyncSample( decoder->TimedTextTrackReader, mediaTime); if(err) goto bail; | |
418 } | |
419 | |
420 bail: | |
421 TEST_RETURN( err ); | |
422 return err; | |
423 } | |
424 | |
425 IMAF_DECODER_API IMAF_Err IMAFDecoder_GetNextAudioSampleByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, | |
426 unsigned char **SampleData, unsigned int *SampleDataSize, unsigned int *CurrentTime, unsigned int *sampleNumber) | |
427 { | |
428 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
429 IMAF_Err err; | |
430 MP4TrackReader reader; | |
431 MP4Handle sampleH; | |
432 u32 unitSize; | |
433 u32 sampleFlags; | |
434 u32 cts; | |
435 u32 dts; | |
436 | |
437 if(i >= decoder->TrackCount - decoder->HasTimedTextTrack) | |
438 BAILWITHERROR(MP4BadParamErr) | |
439 err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; | |
440 err = MP4GetListEntry(decoder->TrackSampleList, i, (char**)&sampleH); if(err) goto bail; | |
441 err = MP4TrackReaderGetNextAccessUnitWithSampleNumber( reader, sampleH, &unitSize,&sampleFlags, &cts, &dts, sampleNumber); | |
442 | |
443 if ( err ) | |
444 { | |
445 if ( err == MP4EOF ) | |
446 { | |
447 *SampleData = NULL; | |
448 *SampleDataSize = 0; | |
449 *CurrentTime = 0; | |
450 err = MP4NoErr; | |
451 } | |
452 else | |
453 goto bail; | |
454 } | |
455 | |
456 *CurrentTime = dts; | |
457 *SampleData = *sampleH; | |
458 *SampleDataSize = unitSize; | |
459 bail: | |
460 TEST_RETURN( err ); | |
461 return err; | |
462 } | |
463 | |
464 IMAF_DECODER_API IMAF_Err IMAFDecoder_GetNextTextSample(IMAF_DecoderH IMafDecoder, | |
465 unsigned char **SampleData, unsigned int *SampleDataSize, unsigned int *CurrentTime, TextSampleStyleParam **param) | |
466 { | |
467 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
468 IMAF_Err err; | |
469 u32 unitSize; | |
470 u32 sampleFlags; | |
471 u32 cts; | |
472 u32 dts; | |
473 u32 i; | |
474 u8 *TextSample; | |
475 MP4InputStreamPtr is; | |
476 u32 TextModifiersSize, TotalAtomSize; | |
477 MP4AtomPtr entry; | |
478 TextStyleAtomPtr styl; | |
479 TextHighlightAtomPtr hlit; | |
480 TextHighlightColorAtomPtr hclr; | |
481 TextKaraokeAtomPtr krok; | |
482 TextSampleEntryValue tx3g_value; | |
483 | |
484 | |
485 err = MP4TrackReaderGetNextAccessUnit(decoder->TimedTextTrackReader, decoder->TimedTextSampleH, &unitSize, &sampleFlags, &cts, &dts); | |
486 | |
487 if ( err ) | |
488 { | |
489 if ( err == MP4EOF ) | |
490 { | |
491 *SampleData = NULL; | |
492 *SampleDataSize = 0; | |
493 *CurrentTime = 0; | |
494 return MP4EOF; | |
495 } | |
496 else | |
497 goto bail; | |
498 } | |
499 | |
500 err = MP4TrackReaderGetTextSampleEntryValues(decoder->TimedTextTrackReader, &tx3g_value); if(err) goto bail; | |
501 | |
502 #if 0 //only text | |
503 *CurrentTime = dts; | |
504 *SampleData = *decoder->TimedTextSampleH; | |
505 *SampleDataSize = unitSize; | |
506 #else | |
507 *CurrentTime = dts; | |
508 TextSample = *decoder->TimedTextSampleH; | |
509 *SampleDataSize = TextSample[0]<<8 | TextSample[1]; | |
510 TextSample+=2; | |
511 MP4SetHandleSize(decoder->TextH, *SampleDataSize+1); | |
512 memcpy(*decoder->TextH, TextSample, *SampleDataSize); | |
513 TextSample += *SampleDataSize; | |
514 (*decoder->TextH)[*SampleDataSize] = '\0'; | |
515 *SampleData = *decoder->TextH; | |
516 | |
517 //Extract Text Style | |
518 InitTextSampleStyleParam(decoder->TextParam); | |
519 decoder->TextParam->displayFlags= tx3g_value.displayFlags; | |
520 decoder->TextParam->horizontal_justification= tx3g_value.horizontal_justification; | |
521 decoder->TextParam->vertical_justification= tx3g_value.vertical_justification; | |
522 decoder->TextParam->background_color_r= tx3g_value.background_color_r; | |
523 decoder->TextParam->background_color_g= tx3g_value.background_color_g; | |
524 decoder->TextParam->background_color_b= tx3g_value.background_color_b; | |
525 decoder->TextParam->background_color_a= tx3g_value.background_color_a; | |
526 decoder->TextParam->default_text_box_top= tx3g_value.default_text_box_top; | |
527 decoder->TextParam->default_text_box_left= tx3g_value.default_text_box_left; | |
528 decoder->TextParam->default_text_box_bottom= tx3g_value.default_text_box_bottom; | |
529 decoder->TextParam->default_text_box_right= tx3g_value.default_text_box_right; | |
530 decoder->TextParam->default_style_startChar= tx3g_value.default_style_startChar; | |
531 decoder->TextParam->default_style_endChar= tx3g_value.default_style_endChar; | |
532 decoder->TextParam->default_style_font_ID= tx3g_value.default_style_font_ID; | |
533 decoder->TextParam->default_style_face_style_flags= tx3g_value.default_style_face_style_flags; | |
534 decoder->TextParam->default_style_font_size= tx3g_value.default_style_font_size; | |
535 decoder->TextParam->default_style_text_color_r= tx3g_value.default_style_text_color_r; | |
536 decoder->TextParam->default_style_text_color_g= tx3g_value.default_style_text_color_g; | |
537 decoder->TextParam->default_style_text_color_b= tx3g_value.default_style_text_color_b; | |
538 decoder->TextParam->default_style_text_color_a= tx3g_value.default_style_text_color_a; | |
539 decoder->TextParam->font_ID= tx3g_value.font_ID; | |
540 decoder->TextParam->font_name_length= tx3g_value.font_name_length; | |
541 decoder->TextParam->font= _strdup(tx3g_value.font); | |
542 free(tx3g_value.font); | |
543 | |
544 TotalAtomSize= 0; | |
545 TextModifiersSize = unitSize - 2 - *SampleDataSize; | |
546 err = MP4CreateMemoryInputStream(TextSample, TextModifiersSize, &is ); if (err) goto bail; | |
547 is->debugging = 0; | |
548 while(TextModifiersSize>TotalAtomSize) | |
549 { | |
550 err = MP4ParseAtom( is, &entry ); if (err) goto bail; | |
551 TotalAtomSize += entry->size; | |
552 if(entry->type == 'styl') | |
553 { | |
554 StyleRecordStructPtr styleRecord; | |
555 styl = (TextStyleAtomPtr)entry; | |
556 decoder->TextParam->styl_entry_count = styl->entry_count; | |
557 decoder->TextParam->styl_text_styles = (StyleRecord*)calloc(styl->entry_count, sizeof(styleRecord)); | |
558 for(i=0; i<styl->entry_count; i++) | |
559 { | |
560 err = MP4GetListEntry(styl->styleRecordList, i, (char**)&styleRecord); if(err) goto bail; | |
561 memcpy(&decoder->TextParam->styl_text_styles[i], styleRecord, sizeof(StyleRecord)); | |
562 } | |
563 } | |
564 else if(entry->type == 'hlit') | |
565 { | |
566 hlit = (TextHighlightAtomPtr)entry; | |
567 decoder->TextParam->hlit_startcharoffset = hlit->startcharoffset; | |
568 decoder->TextParam->hlit_endcharoffset = hlit->endcharoffset; | |
569 } | |
570 else if(entry->type == 'hclr') | |
571 { | |
572 hclr = (TextHighlightColorAtomPtr)entry; | |
573 decoder->TextParam->hclr_highlight_color_r = hclr->highlight_color_r; | |
574 decoder->TextParam->hclr_highlight_color_g = hclr->highlight_color_g; | |
575 decoder->TextParam->hclr_highlight_color_b = hclr->highlight_color_b; | |
576 decoder->TextParam->hclr_highlight_color_a = hclr->highlight_color_a; | |
577 } | |
578 else if(entry->type == 'krok') | |
579 { | |
580 krok = (TextKaraokeAtomPtr)entry; | |
581 decoder->TextParam->krok_highlight_start_time = krok->highlight_start_time; | |
582 decoder->TextParam->krok_entry_count = krok->entry_count; | |
583 decoder->TextParam->krok_highlight_end_time = calloc(krok->entry_count, sizeof(u32)); | |
584 decoder->TextParam->krok_startcharoffset= calloc(krok->entry_count, sizeof(u32)); | |
585 decoder->TextParam->krok_endcharoffset = calloc(krok->entry_count, sizeof(u32)); | |
586 for(i=0; i<krok->entry_count; i++) | |
587 { | |
588 decoder->TextParam->krok_highlight_end_time[i] =krok->highlight_end_time[i]; | |
589 decoder->TextParam->krok_startcharoffset[i] = krok->startcharoffset[i]; | |
590 decoder->TextParam->krok_endcharoffset[i] = krok->endcharoffset[i]; | |
591 } | |
592 } | |
593 else | |
594 { | |
595 BAILWITHERROR(MP4NotImplementedErr) | |
596 } | |
597 | |
598 entry->destroy(entry); | |
599 } | |
600 | |
601 if (is) { | |
602 is->destroy( is ); | |
603 is = NULL; | |
604 } | |
605 | |
606 *param = decoder->TextParam; | |
607 #endif | |
608 | |
609 bail: | |
610 TEST_RETURN( err ); | |
611 return err; | |
612 } | |
613 | |
614 IMAF_DECODER_API IMAF_Err IMAFDecoder_GetDsiByIndex(IMAF_DecoderH IMafDecoder, unsigned int i, char** dsi, unsigned int *dsiSize) | |
615 { | |
616 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
617 IMAF_Err err; | |
618 MP4TrackReader reader; | |
619 MP4Handle specificInfoH; | |
620 | |
621 err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; | |
622 | |
623 err = MP4NewHandle(0, &specificInfoH); if(err) goto bail; | |
624 err = MP4TrackReaderGetCurrentDecoderSpecificInfo(reader, specificInfoH); if(err) goto bail; | |
625 err = MP4GetHandleSize(specificInfoH, dsiSize); | |
626 *dsi = (u8*)malloc(*dsiSize); | |
627 memcpy(*dsi, *specificInfoH, *dsiSize); | |
628 err = MP4DisposeHandle(specificInfoH); if(err) goto bail; | |
629 | |
630 bail: | |
631 TEST_RETURN( err ); | |
632 return err; | |
633 } | |
634 | |
635 IMAF_DECODER_API IMAF_Err IMAFDecoder_GetSongImage(IMAF_DecoderH IMafDecoder, unsigned char **image, unsigned int *imageSize) | |
636 { | |
637 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
638 IMAF_Err err; | |
639 u8 *content_type; | |
640 | |
641 err = MP4GetMovieIndTrack( decoder->moov, 1, &decoder->trak ); if (err) goto bail; | |
642 err = MP4GetTrackMedia( decoder->trak, &decoder->media ); if (err) goto bail; | |
643 err = MP4_GetImageByItemId(decoder->moov, decoder->media, image, imageSize, &content_type, 1); if(err) goto bail; | |
644 | |
645 bail: | |
646 TEST_RETURN( err ); | |
647 return err; | |
648 } | |
649 | |
650 IMAF_DECODER_API IMAF_Err IMAFDecoder_GetMetadata(IMAF_DecoderH IMafDecoder, unsigned char **Meta, unsigned int *MetaSize) | |
651 { | |
652 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
653 IMAF_Err err; | |
654 | |
655 err = MP4GetMetaXml(decoder->moov, Meta, MetaSize); if(err) goto bail; | |
656 bail: | |
657 TEST_RETURN( err ); | |
658 return err; | |
659 } | |
660 | |
661 IMAF_DECODER_API IMAF_Err IMAF_Decoder_Destroy(IMAF_DecoderH IMafDecoder) | |
662 { | |
663 IMAFDecoder *decoder = (IMAFDecoder*) IMafDecoder; | |
664 IMAF_Err err; | |
665 | |
666 if(decoder) | |
667 { | |
668 if(decoder->InputMafFilename) | |
669 { | |
670 free(decoder->InputMafFilename); | |
671 decoder->InputMafFilename = NULL; | |
672 } | |
673 | |
674 if(decoder->TrackReaderList) | |
675 { | |
676 u32 i; | |
677 MP4TrackReader reader; | |
678 MP4Handle sampleH; | |
679 for(i=0; i<decoder->TrackCount - decoder->HasTimedTextTrack; i++) | |
680 { | |
681 err = MP4GetListEntry(decoder->TrackReaderList, i, (char**)&reader); if(err) goto bail; | |
682 err = MP4DisposeTrackReader(reader); if(err) goto bail; | |
683 err = MP4GetListEntry(decoder->TrackSampleList, i, (char**)&sampleH); if(err) goto bail; | |
684 err = MP4DisposeHandle(sampleH); if(err) goto bail; | |
685 } | |
686 err = MP4DeleteLinkedList(decoder->TrackReaderList); if(err) goto bail; | |
687 err = MP4DeleteLinkedList(decoder->TrackSampleList); if(err) goto bail; | |
688 decoder->TrackReaderList = NULL; | |
689 decoder->TrackSampleList = NULL; | |
690 } | |
691 | |
692 if(decoder->TimedTextSampleH) | |
693 MP4DisposeHandle(decoder->TimedTextSampleH); | |
694 if(decoder->TextH) | |
695 MP4DisposeHandle(decoder->TextH); | |
696 if(decoder->TimedTextTrackReader) | |
697 MP4DisposeTrackReader(decoder->TimedTextTrackReader); | |
698 if(decoder->TextParam) | |
699 { | |
700 InitTextSampleStyleParam(decoder->TextParam); | |
701 free(decoder->TextParam); | |
702 } | |
703 | |
704 if(decoder->moov) | |
705 { | |
706 err = MP4DisposeMovie( decoder->moov ); if(err) goto bail; | |
707 } | |
708 free(decoder); | |
709 } | |
710 | |
711 bail: | |
712 return err; | |
713 } | |
714 | |
715 IMAF_DECODER_API char* IMAF_Decoder_GetLastError(IMAF_Err err) | |
716 { | |
717 return MP4GetLastError(err); | |
718 } |