1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  *
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <signal.h>
11 
12 #include "uvoice_types.h"
13 #include "uvoice_player.h"
14 
15 #include "uvoice_os.h"
16 #include "uvoice_common.h"
17 #include "uvoice_play.h"
18 
19 #include "pvmp4audiodecoder_api.h"
20 
21 #define BOX_TYPE_LEN    4
22 #define DECODER_PREPARED 2
23 #define ASC_BUFF_LEN    12
24 
25 #define MP4_ES_DESC_TAG                0x03
26 #define MP4_DEC_CFG_DESC_TAG           0x04
27 #define MP4_DEC_SPEC_DESC_TAG          0x05
28 
29 #define MP4_DECODE_NEXT       0
30 #define MP4_DECODE_STOP       1
31 #define MP4_DECODE_END        2
32 
33 typedef struct {
34     uint32_t box_size;
35     char box_type[BOX_TYPE_LEN];
36 }box_header_t;
37 
38 typedef struct {
39     char major_brand[BOX_TYPE_LEN];
40     int minor_version;
41     char compatible_brands[12];
42 }box_ftyp_t;
43 
44 typedef struct {
45     uint32_t box_size;
46     char box_type[BOX_TYPE_LEN];
47     uint8_t version;
48     uint8_t flags[3];
49     uint32_t creation_time;
50     uint32_t modification_time;
51     uint32_t time_scale;
52     uint32_t duration;
53     uint32_t rate;
54     uint8_t reserved[10];
55     uint8_t matrix[36];
56     uint32_t preview_time;
57     uint32_t post_time;
58     uint32_t selection_time;
59     uint32_t selection_duration;
60     uint32_t current_time;
61     uint32_t next_track_id;
62 }box_mvhd_t;
63 
64 typedef struct {
65     uint8_t version;
66     uint8_t flag[3];
67     uint32_t entry_num;
68 }box_stco_t;
69 
70 typedef struct {
71     uint8_t version;
72     uint8_t flag[3];
73     uint32_t entry_num;
74 }box_stsc_t;
75 
76 typedef struct {
77     uint32_t chunk_id;
78     uint32_t samples;
79     uint32_t id;
80 }entry_info_t;
81 
82 typedef struct {
83     uint8_t version;
84     uint8_t flag[3];
85     uint32_t sample_size;
86     uint32_t sample_count;
87 }box_stsz_t;
88 
89 typedef struct {
90     uint32_t sample_len;
91     uint32_t sample_off;
92 }sample_info_t;
93 
94 typedef struct {
95     char decoder_status;
96     char decoder_find; /* bit 0 esds, bit 1  stsz, bit 2 mdat*/
97     char seek_head;
98     char resv;
99 
100     uint32_t  audio_spec_config_len;
101     uint8_t audio_spec_config_info[ASC_BUFF_LEN];
102     uint32_t sample_count;
103     uint32_t *sample_size_info;
104     uint32_t sample_index;
105     uint32_t unproc_size;
106 
107     uint32_t sample_rate;
108     uint32_t frame_length;
109     int channels;
110 }m4a_decoder_t;
111 
112 static tPVMP4AudioDecoderExternal g_dec_ext;
113 static void *dec_mem = NULL;
114 static uint32_t dec_mem_len = 0;
115 static media_decoder_t *g_aac_mdecoder = NULL;
116 
aac_dec_init(int channels)117 static int aac_dec_init(int channels)
118 {
119     int status = 0;
120 
121     if (dec_mem == NULL) {
122         dec_mem_len = PVMP4AudioDecoderGetMemRequirements();
123         dec_mem = malloc(dec_mem_len);
124         if (0 == dec_mem) {
125             return -1;
126         }
127         memset(dec_mem, 0, dec_mem_len);
128     }
129     else {
130         memset(dec_mem, 0, dec_mem_len);
131     }
132 
133     memset(&g_dec_ext, 0, sizeof(tPVMP4AudioDecoderExternal));
134 
135     g_dec_ext.inputBufferCurrentLength = 0;
136     g_dec_ext.remainderBits = 0;
137     g_dec_ext.inputBufferMaxLength = PVMP4AUDIODECODER_INBUFSIZE;
138     g_dec_ext.outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
139     g_dec_ext.desiredChannels = (int)channels;
140     g_dec_ext.aacPlusEnabled = TRUE;
141 
142     status = PVMP4AudioDecoderInitLibrary(&g_dec_ext, dec_mem);
143     return status;
144 }
145 
aac_dec_deinit()146 static int aac_dec_deinit()
147 {
148     if (NULL != dec_mem) {
149         snd_free(dec_mem);
150         dec_mem = NULL;
151     }
152 
153     dec_mem_len = 0;
154 
155     return 0;
156 }
157 
aac_decoder_config(const uint8_t * in_buffer,uint32_t in_size,int * samplerate,int * channels,int * framelength)158 static int aac_decoder_config(const uint8_t *in_buffer, uint32_t in_size, int *samplerate, int *channels, int *framelength)
159 {
160     int status = 0;
161 
162     g_dec_ext.pInputBuffer = in_buffer;
163     g_dec_ext.inputBufferCurrentLength = in_size;
164     g_dec_ext.pOutputBuffer = NULL;
165 
166     status = PVMP4AudioDecoderConfig(&g_dec_ext, dec_mem);
167 
168     *samplerate = g_dec_ext.samplingRate;
169     *channels = g_dec_ext.encodedChannels;
170 
171     aac_dec_init(*channels);
172     g_dec_ext.pInputBuffer = in_buffer;
173     g_dec_ext.inputBufferCurrentLength = in_size;
174     g_dec_ext.pOutputBuffer = NULL;
175 
176     status = PVMP4AudioDecoderConfig(&g_dec_ext, dec_mem);
177 
178     *framelength = g_dec_ext.frameLength;
179 
180     return status;
181 }
182 
aac_decoder_frame(const uint8_t * in_buffer,uint32_t * in_size,uint8_t * out_buffer,uint32_t * out_size)183 static int aac_decoder_frame(const uint8_t *in_buffer, uint32_t *in_size, uint8_t *out_buffer, uint32_t *out_size)
184 {
185     int status = 0;
186 
187     g_dec_ext.pInputBuffer = in_buffer;
188     g_dec_ext.pOutputBuffer = out_buffer;
189 
190     g_dec_ext.inputBufferCurrentLength = *in_size;
191     g_dec_ext.inputBufferUsedLength = 0;
192 
193     status = PVMP4AudioDecodeFrame(&g_dec_ext, dec_mem);
194 
195     if (MP4AUDEC_SUCCESS == status || SUCCESS == status) {
196         *in_size -= g_dec_ext.inputBufferUsedLength;
197         *out_size = g_dec_ext.frameLength * g_dec_ext.desiredChannels;
198 
199         return status;
200     } else if (MP4AUDEC_INCOMPLETE_FRAME == status) {
201 
202     } else {
203         *in_size = 0;
204     }
205 
206     return status;
207 }
208 
find_box_head(const char * box_type,const uint8_t * in_buf,uint32_t size)209 static int find_box_head(const char *box_type, const uint8_t *in_buf, uint32_t size)
210 {
211     char *f;
212     uint32_t i = 0;
213     int flag = 1;
214 
215     if (size < strlen(box_type)) {
216         return -1;
217     }
218 
219     do {
220         f = (char *)in_buf + i;
221         i++;
222         flag = memcmp(box_type, f, strlen(box_type));
223     } while ((i < size) && (flag));
224 
225     if (flag != 0) {
226         return -1;
227     }
228 
229     return i - 1 + strlen(box_type);
230 }
231 
m4aac_get_sample_size_info(m4a_decoder_t * m4adec,const uint8_t * buffer,uint32_t buff_size)232 static int m4aac_get_sample_size_info(m4a_decoder_t *m4adec, const uint8_t *buffer, uint32_t buff_size)
233 {
234     int i = 0;
235     int offset = 0;
236     int count = 0;
237     uint32_t *sample_size = NULL;
238     int boxtype_offset = 0;
239     uint32_t *sample_size_buf = NULL;
240 
241     m4adec->sample_index = 0;
242 
243     offset = find_box_head("stsz", buffer, buff_size);
244     if ((offset < 0) || (offset >= buff_size)) {
245         m4adec->unproc_size = buff_size - BOX_TYPE_LEN + 1;
246         return 0;
247     }
248 
249     boxtype_offset = offset;
250 
251     if (buff_size - offset < sizeof(box_stsz_t)) {
252         m4adec->unproc_size = buff_size - boxtype_offset;
253         return 0;
254     }
255 
256     box_stsz_t *stsz = (box_stsz_t *)(buffer + offset);
257     memcpy(&count, &stsz->sample_count, sizeof(int));
258     count = UINT32_BIG_2_LIT(count);
259 
260     offset += sizeof(box_stsz_t);
261     sample_size_buf = (uint32_t *)((uint32_t)buffer + offset);
262     sample_size = (uint32_t *)calloc(count * sizeof(uint32_t) + 256, 1);
263 
264     m4adec->sample_count = count;
265 
266     count = MIN(m4adec->sample_count, (buff_size - offset) / sizeof(int));
267 
268     for (i = 0; i < count; i++) {
269         memcpy(&sample_size[i], sample_size_buf + i, sizeof(int));
270         sample_size[i] = UINT32_BIG_2_LIT(sample_size[i]);
271     }
272 
273     m4adec->sample_size_info = sample_size;
274     m4adec->sample_index = count;
275 
276     offset += count * sizeof(int);
277 
278     m4adec->unproc_size = buff_size - offset;
279 
280     return 0;
281 }
282 
m4aac_get_sample_size_remain(m4a_decoder_t * m4adec,const uint8_t * buffer,uint32_t buff_size)283 static int m4aac_get_sample_size_remain(m4a_decoder_t *m4adec, const uint8_t *buffer, uint32_t buff_size)
284 {
285     int i = 0;
286     int offset = 0;
287     int count = 0;
288     uint32_t *sample_size = NULL;
289     int boxtype_offset = 0;
290     uint32_t *sample_size_buf = NULL;
291 
292     sample_size_buf = (uint32_t *)buffer;
293     sample_size = m4adec->sample_size_info;
294 
295     count = MIN(m4adec->sample_count - m4adec->sample_index, (buff_size) / sizeof(int));
296 
297     for (i = 0; i < count; i++) {
298         memcpy(&sample_size[i + m4adec->sample_index], sample_size_buf + i, sizeof(int));
299         sample_size[i + m4adec->sample_index] = UINT32_BIG_2_LIT(sample_size[i + m4adec->sample_index]);
300     }
301 
302     m4adec->sample_index += count;
303 
304     offset += count * sizeof(int);
305 
306     m4adec->unproc_size = buff_size - offset;
307 
308     return 0;
309 }
310 
m4aac_get_mdat(m4a_decoder_t * m4adec,const uint8_t * buffer,uint32_t buff_size)311 static int m4aac_get_mdat(m4a_decoder_t *m4adec, const uint8_t *buffer, uint32_t buff_size)
312 {
313     int offset = 0;
314 
315     offset = find_box_head("mdat", buffer, buff_size);
316     if (offset < 0) {
317         m4adec->unproc_size = buff_size - BOX_TYPE_LEN + 1;
318         return -1;
319     }
320 
321     m4adec->unproc_size = buff_size - offset;
322     return 0;
323 }
324 
convert_to_local_endian(short * buffer,uint32_t samples,char * out_buffer)325 static void convert_to_local_endian(short *buffer, uint32_t samples, char *out_buffer)
326 {
327     int i;
328 
329     for (i = 0; i < samples; i++)
330     {
331         out_buffer[i * 2] = (char)(buffer[i] & 0xFF);
332         out_buffer[i * 2 + 1] = (char)((buffer[i] >> 8) & 0xFF);
333     }
334 }
335 
pcm_output(m4a_decoder_t * m4adec,uint8_t * in_buf,uint32_t samples)336 static void pcm_output(m4a_decoder_t *m4adec, uint8_t *in_buf, uint32_t samples)
337 {
338 	media_decoder_t *mdecoder = g_aac_mdecoder;
339     media_pcminfo_t pcm_info;
340 	memset(&pcm_info, 0, sizeof(pcm_info));
341 
342 	if (!mdecoder->running) {
343 		M_LOGD("samplerate %d, channels %d, samples %d\n",
344 				m4adec->sample_rate,
345 				m4adec->channels,
346 				samples);
347 
348 		pcm_info.rate = m4adec->sample_rate;
349 		if (mdecoder->stere_enable) {
350 			pcm_info.frames = samples * m4adec->channels;
351 			pcm_info.channels = m4adec->channels;
352 		} else {
353 			pcm_info.channels = 1;
354 			pcm_info.frames = samples;
355 		}
356 		pcm_info.bits = 16;
357 		mdecoder->message(mdecoder->priv, PLAYER_MSG_PCM_INFO, &pcm_info);
358 
359 		media_info_t media_info;
360 		memset(&media_info, 0, sizeof(media_info_t));
361 		media_info.bitrate = 0;
362 		mdecoder->message(mdecoder->priv, PLAYER_MSG_MEDIA_INFO, &media_info);
363 		mdecoder->running = 1;
364 	}
365 
366 	if (mdecoder->output &&
367 		mdecoder->output(mdecoder->priv, in_buf, samples * 2)) {
368 		M_LOGE("output failed !\n");
369 		return -1;
370 	}
371 }
372 
m4aac_decode_sample(m4a_decoder_t * m4adec,const uint8_t * buffer,uint32_t buff_size)373 static int m4aac_decode_sample(m4a_decoder_t *m4adec, const uint8_t *buffer, uint32_t buff_size)
374 {
375     int ret = 0;
376     int offset = 0;
377     int i = 0;
378 
379     uint32_t  start_sample = m4adec->sample_index;
380     uint32_t  sample_count = m4adec->sample_count;
381     uint32_t *sample_size_info = m4adec->sample_size_info;
382 
383     uint8_t *readPtr = NULL;
384     uint8_t *sample_buffer = NULL;
385     uint8_t *sample_addr = (uint8_t *)buffer;
386     uint32_t dec_size = 0;
387     uint32_t out_size = 0;
388 
389     offset = 0;
390     sample_buffer = malloc(m4adec->frame_length * 4);
391     for (i = start_sample; i < sample_count; i++) {
392         m4adec->sample_index = i;
393         offset += sample_size_info[i];
394         if (buff_size < offset) {
395             m4adec->unproc_size = buff_size - offset + sample_size_info[i];
396             free(sample_buffer);
397             return 0;
398         }
399 
400         dec_size = sample_size_info[i];
401         out_size = 0;
402         memset(sample_buffer, 0, m4adec->frame_length * 4);
403 
404         aac_decoder_frame(sample_addr, &dec_size, sample_buffer, &out_size);
405 
406         if (out_size != 0) {
407             pcm_output(m4adec, sample_buffer, out_size);
408         }
409 
410         sample_addr += sample_size_info[i];
411     }
412 
413     m4adec->sample_index = sample_count;
414     m4adec->unproc_size = 0;
415     free(sample_buffer);
416 
417     return 0;
418 }
419 
m4aac_get_audio_config(m4a_decoder_t * m4adec,const uint8_t * buffer,uint32_t buff_size)420 static int m4aac_get_audio_config(m4a_decoder_t *m4adec, const uint8_t *buffer, uint32_t buff_size)
421 {
422     int i = 0;
423     int flag = 0;
424     int offset = 0;
425     int esds_size = 0;
426     int boxtype_offset = 0;
427     int next_offset = 0;
428     int asc_size = 0;
429 
430     offset = find_box_head("esds", buffer, buff_size);
431     if ((offset < 0) || (offset >= buff_size)) {
432         m4adec->unproc_size = BOX_TYPE_LEN - 1;
433         return -1;
434     }
435 
436     boxtype_offset = offset;
437 
438     if (buff_size - offset < 10) {
439         goto config_exit;
440     }
441 
442     offset += 4;
443     if (*(buffer + offset) != MP4_ES_DESC_TAG) {
444         goto config_exit;
445     }
446     offset += 1;
447     esds_size = *(buffer + offset);
448     if (esds_size == 0x80) {
449         offset += 3;
450         esds_size = *(buffer + offset);
451     }
452     if (buff_size - offset < esds_size) {
453         goto config_exit;
454     }
455     offset += 1;
456     for (i = 0; i < esds_size; i++) {
457         if (*(buffer + offset + i) == MP4_DEC_CFG_DESC_TAG) {
458             flag = MP4_DEC_CFG_DESC_TAG;
459         }
460         else if ((*(buffer + offset + i) == MP4_DEC_SPEC_DESC_TAG) && (flag == MP4_DEC_CFG_DESC_TAG)) {
461             asc_size = *(buffer + offset + i + 1);
462             if (asc_size == 0x80) {
463                 next_offset = 3;
464                 asc_size = *(buffer + offset + i + 1 + next_offset);
465             }
466             if ((asc_size > ASC_BUFF_LEN) || (i + 1 + next_offset + asc_size > esds_size)) {
467                 continue;
468             }
469             memcpy(m4adec->audio_spec_config_info, buffer + offset + i + 2 + next_offset, asc_size);
470 
471             offset += i + 2 + next_offset + asc_size;
472             m4adec->audio_spec_config_len = asc_size;
473             m4adec->unproc_size = buff_size - offset;
474             return 0;
475         }
476     }
477 config_exit:
478     m4adec->unproc_size = buff_size - boxtype_offset;
479     return -1;
480 }
481 
482 /* esds stsz mdat  */
m4aac_get_audio_info(m4a_decoder_t * m4adec,const uint8_t * buffer,uint32_t buff_size)483 static int m4aac_get_audio_info(m4a_decoder_t *m4adec, const uint8_t *buffer, uint32_t buff_size)
484 {
485     const char *f;
486     int   i = 0;
487     int   j = 0;
488     int   flag = 1;
489     const char *box_type[3] = { "esds", "stsz", "mdat" };
490 
491     if (buff_size < strlen(box_type[0])) {
492         return -1;
493     }
494 
495     do {
496         f = (const char *)buffer + i;
497         i++;
498         for (j = 0; j < 3; j++) {
499             if ((m4adec->decoder_find & (1 << j)) != 0) {
500                 continue;
501             }
502             flag = memcmp(box_type[j], f, strlen(box_type[j]));
503             if (flag == 0) {
504                 if (j != 2) {
505                     m4adec->decoder_status = j;
506                 }
507 
508                 m4adec->decoder_find |= 1 << j;
509 
510                 m4adec->unproc_size = buff_size - (i - 1);
511                 return 0;
512             }
513         }
514 
515     } while (i < buff_size);
516 
517     return -1;
518 }
519 
m4a_decode_buffer(m4a_decoder_t * m4adec,const uint8_t * buffer,uint32_t buff_size)520 static int m4a_decode_buffer(m4a_decoder_t *m4adec, const uint8_t *buffer, uint32_t buff_size)
521 {
522     uint32_t len = 0;
523     int ret = 0;
524 
525     unsigned long samplerate = 0;
526     uint8_t channels = 0;
527 
528     static int decode_status = -1;
529     static uint32_t  sample_index = 0;
530     static uint32_t *sample_size_info = NULL;
531     static uint32_t  sample_count = 0;
532 
533     m4adec->unproc_size = 0;
534 
535     switch (m4adec->decoder_status)
536     {
537     case -1:
538         m4aac_get_audio_info(m4adec, buffer, buff_size);
539         return MP4_DECODE_NEXT;
540         break;
541 
542     case 0:
543         ret = m4aac_get_audio_config(m4adec, buffer, buff_size);
544         if (ret < 0) {
545             return MP4_DECODE_NEXT;
546         }
547 
548         ret = aac_decoder_config(m4adec->audio_spec_config_info, m4adec->audio_spec_config_len, &m4adec->sample_rate, &m4adec->channels, &m4adec->frame_length);
549         if (ret != 0) {
550             M_LOGE("aac_decoder_config fail, ret %d\n", ret);
551             return MP4_DECODE_STOP;
552         }
553 
554         m4adec->decoder_find |= 1;
555 
556         if (m4adec->decoder_find == 3) {
557             m4adec->decoder_status = 3;
558         }
559         else if (m4adec->decoder_find == 7) {
560             m4adec->decoder_status = 3;
561             m4adec->seek_head = 1;
562         }
563         else {
564             m4adec->decoder_status = 1;
565         }
566         return MP4_DECODE_NEXT;
567 
568     case 1:
569         ret = m4aac_get_sample_size_info(m4adec, buffer, buff_size);
570         if (m4adec->sample_count == 0) {
571             return MP4_DECODE_NEXT;
572         }
573         if (m4adec->sample_count == m4adec->sample_index) {
574             m4adec->sample_index = 0;
575             m4adec->decoder_find |= 2;
576 
577             if (m4adec->decoder_find == 3) {
578                 m4adec->decoder_status = 3;
579             }
580             else if (m4adec->decoder_find == 7) {
581                 m4adec->decoder_status = 3;
582                 m4adec->seek_head = 1;
583             }
584             else {
585                 m4adec->decoder_status = 0;
586             }
587             return MP4_DECODE_NEXT;
588         }
589 
590         m4adec->decoder_status = 2;
591         return MP4_DECODE_NEXT;
592 
593     case 2:
594         ret = m4aac_get_sample_size_remain(m4adec, buffer, buff_size);
595         if (m4adec->sample_count == m4adec->sample_index) {
596             m4adec->sample_index = 0;
597 
598             m4adec->decoder_find |= 2;
599 
600             if (m4adec->decoder_find == 3) {
601                 m4adec->decoder_status = 3;
602             }
603             else if (m4adec->decoder_find == 7) {
604                 m4adec->decoder_status = 3;
605                 m4adec->seek_head = 1;
606             }
607             else {
608                 m4adec->decoder_status = 0;
609             }
610         }
611 
612         return MP4_DECODE_NEXT;
613 
614     case 3:
615         ret = m4aac_get_mdat(m4adec, buffer, buff_size);
616         if (ret == 0) {
617             m4adec->decoder_status = 4;
618         }
619 
620         return MP4_DECODE_NEXT;
621 
622     case 4:
623         ret = m4aac_decode_sample(m4adec, buffer, buff_size);
624         if (m4adec->sample_count == m4adec->sample_index) {
625             free(m4adec->sample_size_info);
626             m4adec->sample_size_info = NULL;
627             return MP4_DECODE_END;
628         }
629 
630         return MP4_DECODE_NEXT;
631 
632     default:
633         break;
634     }
635 
636     return MP4_DECODE_STOP;
637 }
638 
m4a_decoder_process(void * priv,const uint8_t * buffer,int nbytes)639 static int m4a_decoder_process(void *priv, const uint8_t *buffer, int nbytes)
640 {
641     media_decoder_t *mdecoder = priv;
642     m4a_decoder_t *m4adec;
643     int ret = 0;
644     int unproc_size = 0;
645 
646     if (!mdecoder) {
647 		M_LOGE("mdecoder null !\n");
648 		return -1;
649 	}
650 
651     g_aac_mdecoder = mdecoder;
652 
653 	m4adec = mdecoder->decoder;
654 	if (!m4adec) {
655 		M_LOGE("pvm4adec null !\n");
656 		return -1;
657 	}
658 
659     ret = m4a_decode_buffer(m4adec, buffer, nbytes);
660     mdecoder->unproc_size = m4adec->unproc_size;
661 
662     if (ret == MP4_DECODE_END) {
663         ret = 0;
664     }
665 
666     return ret;
667 }
668 
m4a_decoder_action(void * priv,player_action_t action,void * arg)669 static int m4a_decoder_action(void *priv, player_action_t action, void *arg)
670 {
671     return 0;
672 }
673 
pvm4a_decoder_create(media_decoder_t * mdecoder)674 int pvm4a_decoder_create(media_decoder_t *mdecoder)
675 {
676     m4a_decoder_t *m4adec;
677     int a1 = 0;
678 
679     if (!mdecoder) {
680         M_LOGE("mdecoder null !\n");
681         return -1;
682     }
683 
684     m4adec = snd_zalloc(sizeof(m4a_decoder_t), AFM_MAIN);
685     if (!m4adec) {
686         M_LOGE("alloc pvm4a decoder failed !\n");
687         return -1;
688     }
689 
690     g_aac_mdecoder = mdecoder;
691 
692     mdecoder->decode = m4a_decoder_process;
693     mdecoder->action = m4a_decoder_action;
694     mdecoder->decoder = m4adec;
695 
696     aac_dec_init(1);
697 
698     M_LOGD("pvm4a decoder create\n");
699     return 0;
700 }
701 
pvm4a_decoder_release(media_decoder_t * mdecoder)702 int pvm4a_decoder_release(media_decoder_t *mdecoder)
703 {
704     m4a_decoder_t *m4adec;
705     if (!mdecoder) {
706         M_LOGE("mdecoder null !\n");
707         return -1;
708     }
709     m4adec = mdecoder->decoder;
710     if (!m4adec) {
711         M_LOGE("pvm4a_decoder null !\n");
712         return -1;
713     }
714 
715     aac_dec_deinit();
716 
717     snd_free(m4adec);
718     mdecoder->decode = NULL;
719     mdecoder->action = NULL;
720     g_aac_mdecoder   = NULL;
721 
722     M_LOGD("pvm4a decoder release\n");
723     return 0;
724 }
725 
726 
727