2 Copyright (c) 2012, Broadcom Europe Ltd
5 Redistribution and use in source and binary forms, with or without
6 modification, 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.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON 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
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "containers/core/containers_private.h"
33 #include "containers/core/containers_io_helpers.h"
34 #include "containers/core/containers_utils.h"
35 #include "containers/core/containers_logging.h"
37 #include "simple_common.h"
39 /******************************************************************************
41 ******************************************************************************/
43 #define MAX_LINE_SIZE 512
45 #define ES_SUFFIX "%s.%2.2i.%4.4s"
46 #define ES_SUFFIX_SIZE 8
48 /******************************************************************************
50 ******************************************************************************/
51 typedef struct VC_CONTAINER_TRACK_MODULE_T
53 VC_CONTAINER_IO_T *io;
58 } VC_CONTAINER_TRACK_MODULE_T;
60 typedef struct VC_CONTAINER_MODULE_T
62 char line[MAX_LINE_SIZE + 1];
64 VC_CONTAINER_TRACK_T *tracks[MAX_TRACKS];
67 } VC_CONTAINER_MODULE_T;
69 /******************************************************************************
71 ******************************************************************************/
72 VC_CONTAINER_STATUS_T simple_writer_open( VC_CONTAINER_T * );
73 static VC_CONTAINER_STATUS_T simple_writer_write( VC_CONTAINER_T *ctx,
74 VC_CONTAINER_PACKET_T *packet );
76 /******************************************************************************
78 ******************************************************************************/
79 static VC_CONTAINER_STATUS_T simple_write_line( VC_CONTAINER_T *ctx,
80 const char *format, ...)
82 VC_CONTAINER_MODULE_T *module = ctx->priv->module;
86 va_start(args, format);
87 result = vsnprintf(module->line, sizeof(module->line), format, args);
90 if (result >= (int)sizeof(module->line))
91 return VC_CONTAINER_ERROR_OUT_OF_RESOURCES;
93 WRITE_BYTES(ctx, module->line, result);
95 return STREAM_STATUS(ctx);
98 static VC_CONTAINER_STATUS_T simple_write_header( VC_CONTAINER_T *ctx )
102 simple_write_line(ctx, SIGNATURE_STRING);
104 for (i = 0; i < ctx->tracks_num; i++)
106 VC_CONTAINER_TRACK_T *track = ctx->tracks[i];
108 if (track->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO)
110 simple_write_line(ctx, "TRACK video, %4.4s, %i, %i",
111 (char *)&track->format->codec,
112 (int)track->format->type->video.width,
113 (int)track->format->type->video.height);
114 if ((track->format->type->video.visible_width &&
115 track->format->type->video.visible_width !=
116 track->format->type->video.width) ||
117 (track->format->type->video.visible_height &&
118 track->format->type->video.visible_height !=
119 track->format->type->video.height))
120 simple_write_line(ctx, CONFIG_VIDEO_CROP" %i, %i",
121 track->format->type->video.visible_width,
122 track->format->type->video.visible_height);
123 if (track->format->type->video.par_num &&
124 track->format->type->video.par_den)
125 simple_write_line(ctx, CONFIG_VIDEO_ASPECT" %i, %i",
126 track->format->type->video.par_num,
127 track->format->type->video.par_den);
129 else if (track->format->es_type == VC_CONTAINER_ES_TYPE_AUDIO)
131 simple_write_line(ctx, "TRACK audio, %4.4s, %i, %i, %i, %i",
132 (char *)&track->format->codec,
133 (int)track->format->type->audio.channels,
134 (int)track->format->type->audio.sample_rate,
135 (int)track->format->type->audio.bits_per_sample,
136 (int)track->format->type->audio.block_align);
138 else if (track->format->es_type == VC_CONTAINER_ES_TYPE_AUDIO)
140 simple_write_line(ctx, "TRACK subpicture, %4.4s, %i",
141 (char *)&track->format->codec,
142 (int)track->format->type->subpicture.encoding);
146 simple_write_line(ctx, "TRACK unknown, %4.4s",
147 (char *)&track->format->codec);
150 simple_write_line(ctx, CONFIG_URI" %s", track->priv->module->io->uri);
151 if (track->format->codec_variant)
152 simple_write_line(ctx, CONFIG_CODEC_VARIANT" %4.4s",
153 (char *)&track->format->codec_variant);
154 if (track->format->bitrate)
155 simple_write_line(ctx, CONFIG_BITRATE" %i", track->format->bitrate);
156 if (!(track->format->flags & VC_CONTAINER_ES_FORMAT_FLAG_FRAMED))
157 simple_write_line(ctx, CONFIG_UNFRAMED);
160 simple_write_line(ctx, SIGNATURE_END_STRING);
162 ctx->priv->module->header_done = true;
163 return STREAM_STATUS(ctx);
166 static VC_CONTAINER_STATUS_T simple_write_config( VC_CONTAINER_T *ctx,
167 unsigned int track_num, VC_CONTAINER_PACKET_T *pkt)
169 VC_CONTAINER_TRACK_T *track = ctx->tracks[track_num];
170 VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
171 VC_CONTAINER_PACKET_T packet;
173 track->priv->module->config_done = true;
175 if (track->format->extradata_size)
177 packet.size = track->format->extradata_size;
178 packet.data = track->format->extradata;
179 packet.track = track_num;
180 packet.pts = pkt ? pkt->pts : VC_CONTAINER_TIME_UNKNOWN;
182 packet.flags |= VC_CONTAINER_PACKET_FLAG_CONFIG;
184 status = simple_writer_write(ctx, &packet);
190 static VC_CONTAINER_STATUS_T simple_write_add_track( VC_CONTAINER_T *ctx,
191 VC_CONTAINER_ES_FORMAT_T *format )
193 VC_CONTAINER_TRACK_T *track = NULL;
194 VC_CONTAINER_STATUS_T status;
195 const char *uri = vc_uri_path(ctx->priv->uri);
196 unsigned int uri_size = strlen(uri);
198 /* Allocate and initialise track data */
199 if (ctx->tracks_num >= MAX_TRACKS)
200 return VC_CONTAINER_ERROR_OUT_OF_RESOURCES;
202 ctx->tracks[ctx->tracks_num] = track =
203 vc_container_allocate_track(ctx, sizeof(VC_CONTAINER_TRACK_MODULE_T) +
204 uri_size + ES_SUFFIX_SIZE + 1);
206 return VC_CONTAINER_ERROR_OUT_OF_MEMORY;
208 if (format->extradata_size)
210 status = vc_container_track_allocate_extradata(ctx, track, format->extradata_size);
211 if (status != VC_CONTAINER_SUCCESS)
214 vc_container_format_copy(track->format, format, format->extradata_size);
216 track->priv->module->uri = (char *)&track->priv->module[1];
217 snprintf(track->priv->module->uri, uri_size + ES_SUFFIX_SIZE + 1,
218 ES_SUFFIX, uri, ctx->tracks_num, (char *)&track->format->codec);
220 LOG_DEBUG(ctx, "opening elementary stream: %s", track->priv->module->uri);
221 track->priv->module->io = vc_container_io_open(track->priv->module->uri,
222 VC_CONTAINER_IO_MODE_WRITE, &status);
223 if (status != VC_CONTAINER_SUCCESS)
225 LOG_ERROR(ctx, "error opening elementary stream: %s",
226 track->priv->module->uri);
231 return VC_CONTAINER_SUCCESS;
235 vc_container_free_track(ctx, track);
239 /*****************************************************************************
240 Functions exported as part of the Container Module API
241 *****************************************************************************/
242 static VC_CONTAINER_STATUS_T simple_writer_close( VC_CONTAINER_T *ctx )
244 VC_CONTAINER_MODULE_T *module = ctx->priv->module;
245 for (; ctx->tracks_num > 0; ctx->tracks_num--)
247 vc_container_io_close(ctx->tracks[ctx->tracks_num-1]->priv->module->io);
248 vc_container_free_track(ctx, ctx->tracks[ctx->tracks_num-1]);
251 return VC_CONTAINER_SUCCESS;
254 /*****************************************************************************/
255 static VC_CONTAINER_STATUS_T simple_writer_write( VC_CONTAINER_T *ctx,
256 VC_CONTAINER_PACKET_T *packet )
258 VC_CONTAINER_STATUS_T status;
260 if (!ctx->priv->module->header_done)
262 status = simple_write_header(ctx);
263 if (status != VC_CONTAINER_SUCCESS)
267 if (!ctx->tracks[packet->track]->priv->module->config_done)
269 status = simple_write_config(ctx, packet->track, packet);
270 if (status != VC_CONTAINER_SUCCESS)
274 /* Write the metadata */
275 status = simple_write_line(ctx, "%i %i %"PRIi64" 0x%x",
276 (int)packet->track, (int)packet->size, packet->pts, packet->flags);
277 if (status != VC_CONTAINER_SUCCESS)
280 /* Write the elementary stream */
281 vc_container_io_write(ctx->tracks[packet->track]->priv->module->io,
282 packet->data, packet->size);
284 return STREAM_STATUS(ctx);
287 /*****************************************************************************/
288 static VC_CONTAINER_STATUS_T simple_writer_control( VC_CONTAINER_T *ctx,
289 VC_CONTAINER_CONTROL_T operation, va_list args )
291 VC_CONTAINER_ES_FORMAT_T *format;
295 case VC_CONTAINER_CONTROL_TRACK_ADD:
296 format = (VC_CONTAINER_ES_FORMAT_T *)va_arg(args, VC_CONTAINER_ES_FORMAT_T *);
297 return simple_write_add_track(ctx, format);
299 case VC_CONTAINER_CONTROL_TRACK_ADD_DONE:
300 simple_write_header( ctx );
301 return VC_CONTAINER_SUCCESS;
303 default: return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
307 /*****************************************************************************/
308 VC_CONTAINER_STATUS_T simple_writer_open( VC_CONTAINER_T *ctx )
310 VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FORMAT_INVALID;
311 const char *extension = vc_uri_path_extension(ctx->priv->uri);
312 VC_CONTAINER_MODULE_T *module;
314 /* Check if the user has specified a container */
315 vc_uri_find_query(ctx->priv->uri, 0, "container", &extension);
317 /* Check we're the right writer for this */
319 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
320 if(strcasecmp(extension, "smpl") && strcasecmp(extension, "simple"))
321 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
323 LOG_DEBUG(ctx, "using simple writer");
325 /* Allocate our context */
326 module = malloc(sizeof(*module));
327 if (!module) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; }
328 memset(module, 0, sizeof(*module));
329 ctx->priv->module = module;
330 ctx->tracks = module->tracks;
332 ctx->priv->pf_close = simple_writer_close;
333 ctx->priv->pf_write = simple_writer_write;
334 ctx->priv->pf_control = simple_writer_control;
335 return VC_CONTAINER_SUCCESS;
338 LOG_DEBUG(ctx, "simple: error opening stream (%i)", status);
342 /********************************************************************************
344 ********************************************************************************/
346 #if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__)
347 # pragma weak writer_open simple_writer_open