1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27#include <stdlib.h>
28#include <string.h>
29
30#include "containers/core/containers_private.h"
31#include "containers/core/containers_io_helpers.h"
32#include "containers/core/containers_utils.h"
33#include "containers/core/containers_logging.h"
34
35/******************************************************************************
36Defines.
37******************************************************************************/
38#define DEFAULT_BLOCK_SIZE (1024*16)
39/* Work-around for JPEG because our decoder expects that much at the start */
40#define DEFAULT_JPEG_BLOCK_SIZE (1024*80)
41
42/******************************************************************************
43Type definitions
44******************************************************************************/
45typedef struct VC_CONTAINER_MODULE_T
46{
47 VC_CONTAINER_TRACK_T *track;
48 unsigned int default_block_size;
49 unsigned int block_size;
50 bool init;
51
52 VC_CONTAINER_STATUS_T status;
53
54} VC_CONTAINER_MODULE_T;
55
56static struct
57{
58 const char *ext;
59 VC_CONTAINER_ES_TYPE_T type;
60 VC_CONTAINER_FOURCC_T codec;
61
62} extension_to_format_table[] =
63{
64 /* Audio */
65 {"mp3", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_MPGA},
66 {"aac", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_MP4A},
67 {"adts", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_MP4A},
68 {"ac3", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_AC3},
69 {"ec3", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_EAC3},
70 {"amr", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_AMRNB},
71 {"awb", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_AMRWB},
72 {"evrc", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_EVRC},
73 {"dts", VC_CONTAINER_ES_TYPE_AUDIO, VC_CONTAINER_CODEC_DTS},
74
75 /* Video */
76 {"m1v", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_MP1V},
77 {"m2v", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_MP2V},
78 {"m4v", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_MP4V},
79 {"mp4v", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_MP4V},
80 {"h263", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_H263},
81 {"263", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_H263},
82 {"h264", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_H264},
83 {"264", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_H264},
84 {"mvc", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_MVC},
85 {"vc1l", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_WVC1},
86
87 /* Image */
88 {"gif", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_GIF},
89 {"jpg", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_JPEG},
90 {"jpeg", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_JPEG},
91 {"png", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_PNG},
92 {"ppm", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_PPM},
93 {"tga", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_TGA},
94 {"bmp", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_BMP},
95
96 {"bin", 0, 0},
97 {0, 0, 0}
98};
99
100static struct
101{
102 const char *ext;
103 VC_CONTAINER_ES_TYPE_T type;
104 VC_CONTAINER_FOURCC_T codec;
105
106} bin_extension_to_format_table[] =
107{
108 {"m4v.bin", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_MP4V},
109 {"263.bin", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_H263},
110 {"264.bin", VC_CONTAINER_ES_TYPE_VIDEO, VC_CONTAINER_CODEC_H264},
111 {0, 0, 0}
112};
113
114/******************************************************************************
115Function prototypes
116******************************************************************************/
117VC_CONTAINER_STATUS_T binary_reader_open( VC_CONTAINER_T * );
118
119/******************************************************************************
120Local Functions
121******************************************************************************/
122
123/*****************************************************************************
124Functions exported as part of the Container Module API
125 *****************************************************************************/
126static VC_CONTAINER_STATUS_T binary_reader_read( VC_CONTAINER_T *p_ctx,
127 VC_CONTAINER_PACKET_T *packet, uint32_t flags )
128{
129 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
130 unsigned int size;
131
132 if(module->status != VC_CONTAINER_SUCCESS)
133 return module->status;
134
135 if(!module->block_size)
136 {
137 module->block_size = module->default_block_size;
138 module->init = 0;
139 }
140
141 packet->size = module->block_size;
142 packet->dts = packet->pts = VC_CONTAINER_TIME_UNKNOWN;
143 if(module->init) packet->dts = packet->pts = 0;
144 packet->track = 0;
145 packet->flags = 0;
146
147 if(flags & VC_CONTAINER_READ_FLAG_SKIP)
148 {
149 size = SKIP_BYTES(p_ctx, module->block_size);
150 module->block_size -= size;
151 module->status = STREAM_STATUS(p_ctx);
152 return module->status;
153 }
154
155 if(flags & VC_CONTAINER_READ_FLAG_INFO)
156 return VC_CONTAINER_SUCCESS;
157
158 size = MIN(module->block_size, packet->buffer_size);
159 size = READ_BYTES(p_ctx, packet->data, size);
160 module->block_size -= size;
161 packet->size = size;
162
163 module->status = size ? VC_CONTAINER_SUCCESS : STREAM_STATUS(p_ctx);
164 return module->status;
165}
166
167/*****************************************************************************/
168static VC_CONTAINER_STATUS_T binary_reader_seek( VC_CONTAINER_T *p_ctx, int64_t *offset,
169 VC_CONTAINER_SEEK_MODE_T mode, VC_CONTAINER_SEEK_FLAGS_T flags)
170{
171 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
172 VC_CONTAINER_PARAM_UNUSED(module);
173 VC_CONTAINER_PARAM_UNUSED(offset);
174 VC_CONTAINER_PARAM_UNUSED(mode);
175 VC_CONTAINER_PARAM_UNUSED(flags);
176 return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
177}
178
179/*****************************************************************************/
180static VC_CONTAINER_STATUS_T binary_reader_close( VC_CONTAINER_T *p_ctx )
181{
182 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
183 for(; p_ctx->tracks_num > 0; p_ctx->tracks_num--)
184 vc_container_free_track(p_ctx, p_ctx->tracks[p_ctx->tracks_num-1]);
185 free(module);
186 return VC_CONTAINER_SUCCESS;
187}
188
189/*****************************************************************************/
190VC_CONTAINER_STATUS_T binary_reader_open( VC_CONTAINER_T *p_ctx )
191{
192 const char *extension = vc_uri_path_extension(p_ctx->priv->uri);
193 VC_CONTAINER_MODULE_T *module = 0;
194 VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FORMAT_INVALID;
195 VC_CONTAINER_ES_TYPE_T es_type = 0;
196 VC_CONTAINER_FOURCC_T codec = 0;
197 unsigned int i;
198
199 /* Check if the user has specified a container */
200 vc_uri_find_query(p_ctx->priv->uri, 0, "container", &extension);
201
202 /* Check if the extension is supported */
203 if(!extension || !vc_uri_path(p_ctx->priv->uri))
204 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
205 for(i = 0; extension_to_format_table[i].ext; i++)
206 {
207 if(strcasecmp(extension, extension_to_format_table[i].ext))
208 continue;
209
210 es_type = extension_to_format_table[i].type;
211 codec = extension_to_format_table[i].codec;
212 break;
213 }
214 if(!extension_to_format_table[i].ext) return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
215
216 /* If this a .bin file we look in our bin list */
217 for(i = 0; !codec && bin_extension_to_format_table[i].ext; i++)
218 {
219 if(!strstr(vc_uri_path(p_ctx->priv->uri), bin_extension_to_format_table[i].ext) &&
220 !strstr(extension, bin_extension_to_format_table[i].ext))
221 continue;
222
223 es_type = bin_extension_to_format_table[i].type;
224 codec = bin_extension_to_format_table[i].codec;
225 break;
226 }
227 if(!codec) return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
228
229 /* Allocate our context */
230 module = malloc(sizeof(*module));
231 if(!module) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; }
232 memset(module, 0, sizeof(*module));
233 p_ctx->priv->module = module;
234 p_ctx->tracks_num = 1;
235 p_ctx->tracks = &module->track;
236 p_ctx->tracks[0] = vc_container_allocate_track(p_ctx, 0);
237 if(!p_ctx->tracks[0]) return VC_CONTAINER_ERROR_OUT_OF_MEMORY;
238 p_ctx->tracks[0]->format->es_type = es_type;
239 p_ctx->tracks[0]->format->codec = codec;
240 p_ctx->tracks[0]->is_enabled = true;
241 module->default_block_size = DEFAULT_BLOCK_SIZE;
242 if(codec == VC_CONTAINER_CODEC_JPEG)
243 module->default_block_size = DEFAULT_JPEG_BLOCK_SIZE;
244 module->block_size = module->default_block_size;
245 module->init = 1;
246
247 /*
248 * We now have all the information we really need to start playing the stream
249 */
250
251 p_ctx->priv->pf_close = binary_reader_close;
252 p_ctx->priv->pf_read = binary_reader_read;
253 p_ctx->priv->pf_seek = binary_reader_seek;
254 return VC_CONTAINER_SUCCESS;
255
256 error:
257 LOG_DEBUG(p_ctx, "binary: error opening stream (%i)", status);
258 return status;
259}
260
261/********************************************************************************
262 Entrypoint function
263 ********************************************************************************/
264
265#if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__)
266# pragma weak reader_open binary_reader_open
267#endif
268