1 /******************************************************************************
2  *                                                                            *
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #include <stdlib.h>
21 #include <string.h>
22 #ifndef CORTEX_M4
23 #include <stdio.h>
24 #else
25 #include "cm4_file_operations.h"
26 #endif
27 #include <assert.h>
28 
29 #include "ixheaacd_fileifc.h"
30 #ifndef min
31 #define min(a, b) (((a) < (b)) ? (a) : (b))
32 #endif
33 
34 //#define INCLUDE_MP4_PARSER
35 
36 FileWrapperPtr FileWrapper_Open(char fileName[]) {
37   FileWrapperPtr transport = (FileWrapper *)calloc(1, sizeof(FileWrapper));
38 
39   transport->isMp4File = 0;
40   transport->inputFile = NULL;
41 
42 #ifdef INCLUDE_MP4_PARSER
43 
44   transport->header_given = 0;
45   transport->fileCtxt = 0;
46   transport->mp4Ctxt = 0;
47   transport->interim_buffer = 0;
48   transport->avail_buffer = 0;
49 
50   if ((transport->fileCtxt = it_fopen((void *)fileName, 1, 0)) == NULL) {
51     transport->inputFile = fopen(fileName, "rb");
52     if (!transport->inputFile) {
53       free(transport);
54       return 0;
55     }
56 
57     else
58       return transport;
59   }
60 
61   if ((transport->mp4Ctxt = it_mp4_parser_init(transport->fileCtxt, NULL)) ==
62       NULL) {
63     transport->inputFile = fopen(fileName, "rb");
64     if (!transport->inputFile) {
65       free(transport);
66       return 0;
67     } else
68       return transport;
69   }
70   transport->isMp4File = 1;
71   /* 768 * max channels is the max audio block size for AAC */
72   /* As max channels is 8 and +2 for upto two Ind CoupCh */
73   transport->interim_buffer = malloc(10 * 768);
74   if (transport->interim_buffer == NULL) {
75     free(transport);
76     return 0;
77   }
78   return transport;
79 #else
80   transport->inputFile = fopen(fileName, "rb");
81   if (!transport->inputFile) {
82     free(transport);
83     return 0;
84   } else
85     return transport;
86 #endif
87 }
88 
89 int FileWrapper_Read(FileWrapperPtr transport, unsigned char *buffer,
90                      int bufSize, unsigned int *length) {
91 #ifdef INCLUDE_MP4_PARSER
92   if (!transport->isMp4File)
93     *length = fread(buffer, 1, bufSize, transport->inputFile);
94   else {
95     int errorCode;
96     if (transport->header_given == 0) {
97       transport->headerCtxt.header = (void *)buffer;
98       /* MP4 Hook: Audio Header data to be put in buffer pointed by
99       // headerCtxt.header and length to be put in headerCtxt.headerLength*/
100       errorCode =
101           it_mp4_get_audio_header(transport->mp4Ctxt, &transport->headerCtxt);
102       transport->header_given = 1;
103       if (errorCode != 0) /* IT_OK = 0 */
104       {
105         *length = 0;
106         return 1;
107       }
108       *length = transport->headerCtxt.headerLength;
109     } else {
110       *length = 0;
111 /* MP4 Hook: Audio Data to be put in buffer pointed by frameCtxt.header*/
112 #ifndef ENABLE_LD_DEC
113       while ((int)*length < bufSize)
114 #endif
115       {
116         if (transport->avail_buffer == 0) {
117           transport->frameCtxt.frame = (void *)transport->interim_buffer;
118           errorCode =
119               it_mp4_get_audio(transport->mp4Ctxt, &transport->frameCtxt);
120           if (errorCode != 0) /* IT_OK = 0 */
121           {
122             if (*length == 0)
123               return 1;
124             else
125 #ifndef ENABLE_LD_DEC
126               break;
127 #else
128               return 1;
129 #endif
130           }
131           transport->avail_buffer += transport->frameCtxt.frameLength;
132         }
133 #ifndef ENABLE_LD_DEC
134         else
135 #endif
136         {
137           int size_to_cpy =
138               min((int)(bufSize - *length), transport->avail_buffer);
139           memcpy(buffer + (*length), transport->interim_buffer, size_to_cpy);
140           memmove(transport->interim_buffer,
141                   ((char *)transport->interim_buffer) + size_to_cpy,
142                   (transport->avail_buffer - size_to_cpy));
143           *length += size_to_cpy;
144           transport->avail_buffer -= size_to_cpy;
145         }
146       }
147     }
148 #ifdef DEBUG_ASSERT
149     assert(*length <= (unsigned)bufSize);
150 #endif
151   }
152 
153 #else
154   *length = fread(buffer, 1, bufSize, transport->inputFile);
155 #endif
156 
157   return 0;
158 }
159 
160 unsigned int FileWrapper_Close(FileWrapperPtr transport) {
161   if (transport == 0) return 0;
162 
163 #ifdef INCLUDE_MP4_PARSER
164   if (transport->isMp4File) {
165     it_mp4_parser_close(transport->mp4Ctxt);
166     it_fclose(transport->fileCtxt);
167   } else
168 #endif
169       if (transport->inputFile)
170     fclose(transport->inputFile);
171 
172   free(transport);
173   return 0;
174 }
175 
176 unsigned int FileWrapper_IsMp4File(FileWrapperPtr transport) {
177   return transport->isMp4File;
178 }
179