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 "raw_video_common.h"
39 /******************************************************************************
41 ******************************************************************************/
43 /******************************************************************************
45 ******************************************************************************/
46 typedef struct VC_CONTAINER_MODULE_T
48 VC_CONTAINER_TRACK_T *track;
53 } VC_CONTAINER_MODULE_T;
55 /******************************************************************************
57 ******************************************************************************/
58 VC_CONTAINER_STATUS_T rawvideo_writer_open( VC_CONTAINER_T * );
60 /******************************************************************************
62 ******************************************************************************/
63 static VC_CONTAINER_STATUS_T rawvideo_write_header( VC_CONTAINER_T *ctx )
65 VC_CONTAINER_MODULE_T *module = ctx->priv->module;
70 size = snprintf(line, sizeof(line), "YUV4MPEG2 W%i H%i",
71 ctx->tracks[0]->format->type->video.width,
72 ctx->tracks[0]->format->type->video.height);
73 if (size >= sizeof(line))
74 return VC_CONTAINER_ERROR_OUT_OF_RESOURCES;
75 WRITE_BYTES(ctx, line, size);
77 if (ctx->tracks[0]->format->type->video.frame_rate_num &&
78 ctx->tracks[0]->format->type->video.frame_rate_den)
80 size = snprintf(line, sizeof(line), " F%i:%i",
81 ctx->tracks[0]->format->type->video.frame_rate_num,
82 ctx->tracks[0]->format->type->video.frame_rate_den);
83 if (size >= sizeof(line))
84 return VC_CONTAINER_ERROR_OUT_OF_RESOURCES;
85 WRITE_BYTES(ctx, line, size);
88 if (ctx->tracks[0]->format->type->video.par_num &&
89 ctx->tracks[0]->format->type->video.par_den)
91 size = snprintf(line, sizeof(line), " A%i:%i",
92 ctx->tracks[0]->format->type->video.par_num,
93 ctx->tracks[0]->format->type->video.par_den);
94 if (size >= sizeof(line))
95 return VC_CONTAINER_ERROR_OUT_OF_RESOURCES;
96 WRITE_BYTES(ctx, line, size);
99 if (to_yuv4mpeg2(ctx->tracks[0]->format->codec, &id, 0, 0))
101 size = snprintf(line, sizeof(line), " C%s", id);
105 module->non_standard = true;
106 size = snprintf(line, sizeof(line), " C%4.4s",
107 (char *)&ctx->tracks[0]->format->codec);
109 if (size >= sizeof(line))
110 return VC_CONTAINER_ERROR_OUT_OF_RESOURCES;
111 WRITE_BYTES(ctx, line, size);
113 _WRITE_U8(ctx, 0x0a);
114 module->header_done = true;
115 return STREAM_STATUS(ctx);
118 static VC_CONTAINER_STATUS_T simple_write_add_track( VC_CONTAINER_T *ctx,
119 VC_CONTAINER_ES_FORMAT_T *format )
121 VC_CONTAINER_STATUS_T status;
123 /* Sanity check that we support the type of track being created */
125 return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
126 if (format->es_type != VC_CONTAINER_ES_TYPE_VIDEO)
127 return VC_CONTAINER_ERROR_TRACK_FORMAT_NOT_SUPPORTED;
129 /* Allocate and initialise track data */
130 ctx->tracks[0] = vc_container_allocate_track(ctx, 0);
132 return VC_CONTAINER_ERROR_OUT_OF_MEMORY;
134 status = vc_container_track_allocate_extradata(ctx,
135 ctx->tracks[0], format->extradata_size);
136 if(status != VC_CONTAINER_SUCCESS)
139 vc_container_format_copy(ctx->tracks[0]->format, format,
140 format->extradata_size);
142 return VC_CONTAINER_SUCCESS;
145 /*****************************************************************************
146 Functions exported as part of the Container Module API
147 *****************************************************************************/
148 static VC_CONTAINER_STATUS_T rawvideo_writer_close( VC_CONTAINER_T *ctx )
150 VC_CONTAINER_MODULE_T *module = ctx->priv->module;
151 for (; ctx->tracks_num > 0; ctx->tracks_num--)
152 vc_container_free_track(ctx, ctx->tracks[ctx->tracks_num-1]);
154 return VC_CONTAINER_SUCCESS;
157 /*****************************************************************************/
158 static VC_CONTAINER_STATUS_T rawvideo_writer_write( VC_CONTAINER_T *ctx,
159 VC_CONTAINER_PACKET_T *packet )
161 VC_CONTAINER_MODULE_T *module = ctx->priv->module;
162 VC_CONTAINER_STATUS_T status;
164 if (module->yuv4mpeg2 && !module->header_done)
166 status = rawvideo_write_header(ctx);
167 if (status != VC_CONTAINER_SUCCESS)
171 if (module->yuv4mpeg2 &&
172 (packet->flags & VC_CONTAINER_PACKET_FLAG_FRAME_START))
174 /* Write the metadata */
175 WRITE_BYTES(ctx, "FRAME", sizeof("FRAME")-1);
177 /* For formats not supported by the YUV4MPEG2 spec, we prepend
178 * each frame with its size */
179 if (module->non_standard)
183 size = snprintf(line, sizeof(line), " S%i",
184 packet->frame_size ? packet->frame_size : packet->size);
185 if (size < sizeof(line))
186 WRITE_BYTES(ctx, line, size);
189 _WRITE_U8(ctx, 0x0a);
192 /* Write the elementary stream */
193 WRITE_BYTES(ctx, packet->data, packet->size);
195 return STREAM_STATUS(ctx);
198 /*****************************************************************************/
199 static VC_CONTAINER_STATUS_T rawvideo_writer_control( VC_CONTAINER_T *ctx,
200 VC_CONTAINER_CONTROL_T operation, va_list args )
202 VC_CONTAINER_MODULE_T *module = ctx->priv->module;
203 VC_CONTAINER_ES_FORMAT_T *format;
207 case VC_CONTAINER_CONTROL_TRACK_ADD:
208 format = (VC_CONTAINER_ES_FORMAT_T *)va_arg(args, VC_CONTAINER_ES_FORMAT_T *);
209 return simple_write_add_track(ctx, format);
211 case VC_CONTAINER_CONTROL_TRACK_ADD_DONE:
212 return module->yuv4mpeg2 ?
213 rawvideo_write_header( ctx ) : VC_CONTAINER_SUCCESS;
215 default: return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
219 /*****************************************************************************/
220 VC_CONTAINER_STATUS_T rawvideo_writer_open( VC_CONTAINER_T *ctx )
222 VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FORMAT_INVALID;
223 const char *extension = vc_uri_path_extension(ctx->priv->uri);
224 VC_CONTAINER_MODULE_T *module;
225 bool yuv4mpeg2 = false;
227 /* Check if the user has specified a container */
228 vc_uri_find_query(ctx->priv->uri, 0, "container", &extension);
230 /* Check we're the right writer for this */
232 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
233 if(!strcasecmp(extension, "y4m") || !strcasecmp(extension, "yuv4mpeg2"))
235 if(!yuv4mpeg2 && strcasecmp(extension, "yuv"))
236 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
238 LOG_DEBUG(ctx, "using rawvideo writer");
240 /* Allocate our context */
241 module = malloc(sizeof(*module));
242 if (!module) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; }
243 memset(module, 0, sizeof(*module));
244 ctx->priv->module = module;
245 ctx->tracks = &module->track;
246 module->yuv4mpeg2 = yuv4mpeg2;
248 ctx->priv->pf_close = rawvideo_writer_close;
249 ctx->priv->pf_write = rawvideo_writer_write;
250 ctx->priv->pf_control = rawvideo_writer_control;
251 return VC_CONTAINER_SUCCESS;
254 LOG_DEBUG(ctx, "rawvideo: error opening stream (%i)", status);
258 /********************************************************************************
260 ********************************************************************************/
262 #if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__)
263 # pragma weak writer_open rawvideo_writer_open