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       return 0;
54     else
55       return transport;
56   }
57 
58   if ((transport->mp4Ctxt = it_mp4_parser_init(transport->fileCtxt, NULL)) ==
59       NULL) {
60     transport->inputFile = fopen(fileName, "rb");
61     if (!transport->inputFile)
62       return 0;
63     else
64       return transport;
65   }
66   transport->isMp4File = 1;
67   /* 768 * max channels is the max audio block size for AAC */
68   /* As max channels is 8 and +2 for upto two Ind CoupCh */
69   transport->interim_buffer = malloc(10 * 768);
70   if (transport->interim_buffer == NULL) {
71     return 0;
72   }
73   return transport;
74 #else
75   transport->inputFile = fopen(fileName, "rb");
76   if (!transport->inputFile)
77     return 0;
78   else
79     return transport;
80 #endif
81 }
82 
83 int FileWrapper_Read(FileWrapperPtr transport, unsigned char *buffer,
84                      int bufSize, unsigned int *length) {
85 #ifdef INCLUDE_MP4_PARSER
86   if (!transport->isMp4File)
87     *length = fread(buffer, 1, bufSize, transport->inputFile);
88   else {
89     int errorCode;
90     if (transport->header_given == 0) {
91       transport->headerCtxt.header = (void *)buffer;
92       /* MP4 Hook: Audio Header data to be put in buffer pointed by
93       // headerCtxt.header and length to be put in headerCtxt.headerLength*/
94       errorCode =
95           it_mp4_get_audio_header(transport->mp4Ctxt, &transport->headerCtxt);
96       transport->header_given = 1;
97       if (errorCode != 0) /* IT_OK = 0 */
98       {
99         *length = 0;
100         return 1;
101       }
102       *length = transport->headerCtxt.headerLength;
103     } else {
104       *length = 0;
105 /* MP4 Hook: Audio Data to be put in buffer pointed by frameCtxt.header*/
106 #ifndef ENABLE_LD_DEC
107       while ((int)*length < bufSize)
108 #endif
109       {
110         if (transport->avail_buffer == 0) {
111           transport->frameCtxt.frame = (void *)transport->interim_buffer;
112           errorCode =
113               it_mp4_get_audio(transport->mp4Ctxt, &transport->frameCtxt);
114           if (errorCode != 0) /* IT_OK = 0 */
115           {
116             if (*length == 0)
117               return 1;
118             else
119 #ifndef ENABLE_LD_DEC
120               break;
121 #else
122               return 1;
123 #endif
124           }
125           transport->avail_buffer += transport->frameCtxt.frameLength;
126         }
127 #ifndef ENABLE_LD_DEC
128         else
129 #endif
130         {
131           int size_to_cpy =
132               min((int)(bufSize - *length), transport->avail_buffer);
133           memcpy(buffer + (*length), transport->interim_buffer, size_to_cpy);
134           memmove(transport->interim_buffer,
135                   ((char *)transport->interim_buffer) + size_to_cpy,
136                   (transport->avail_buffer - size_to_cpy));
137           *length += size_to_cpy;
138           transport->avail_buffer -= size_to_cpy;
139         }
140       }
141     }
142 #ifdef DEBUG_ASSERT
143     assert(*length <= (unsigned)bufSize);
144 #endif
145   }
146 
147 #else
148   *length = fread(buffer, 1, bufSize, transport->inputFile);
149 #endif
150 
151   return 0;
152 }
153 
154 unsigned int FileWrapper_Close(FileWrapperPtr transport) {
155   if (transport == 0) return 0;
156 
157 #ifdef INCLUDE_MP4_PARSER
158   if (transport->isMp4File) {
159     it_mp4_parser_close(transport->mp4Ctxt);
160     it_fclose(transport->fileCtxt);
161   } else
162 #endif
163       if (transport->inputFile)
164     fclose(transport->inputFile);
165 
166   free(transport);
167   return 0;
168 }
169 
170 unsigned int FileWrapper_IsMp4File(FileWrapperPtr transport) {
171   return transport->isMp4File;
172 }
173