1
/* $Id: format.c 4785 2014-03-10 09:01:18Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include <pjmedia/format.h>
21
#include <pj/assert.h>
24
#include <pj/string.h>
27
PJ_DEF(pjmedia_audio_format_detail*)
28
pjmedia_format_get_audio_format_detail(const pjmedia_format *fmt,
29
pj_bool_t assert_valid)
31
if (fmt->detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO) {
32
return (pjmedia_audio_format_detail*) &fmt->det.aud;
34
/* Get rid of unused var compiler warning if pj_assert()
35
* macro does not do anything
37
PJ_UNUSED_ARG(assert_valid);
38
pj_assert(!assert_valid || !"Invalid audio format detail");
44
PJ_DEF(pjmedia_format*) pjmedia_format_copy(pjmedia_format *dst,
45
const pjmedia_format *src)
47
return (pjmedia_format*)pj_memcpy(dst, src, sizeof(*src));
51
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
54
static pj_status_t apply_packed_fmt(const pjmedia_video_format_info *fi,
55
pjmedia_video_apply_fmt_param *aparam);
57
static pj_status_t apply_planar_420(const pjmedia_video_format_info *fi,
58
pjmedia_video_apply_fmt_param *aparam);
60
static pj_status_t apply_planar_422(const pjmedia_video_format_info *fi,
61
pjmedia_video_apply_fmt_param *aparam);
63
static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi,
64
pjmedia_video_apply_fmt_param *aparam);
66
struct pjmedia_video_format_mgr
70
pjmedia_video_format_info **infos;
73
static pjmedia_video_format_mgr *video_format_mgr_instance;
74
static pjmedia_video_format_info built_in_vid_fmt_info[] =
76
{PJMEDIA_FORMAT_RGB24, "RGB24", PJMEDIA_COLOR_MODEL_RGB, 24, 1, &apply_packed_fmt},
77
{PJMEDIA_FORMAT_RGBA, "RGBA", PJMEDIA_COLOR_MODEL_RGB, 32, 1, &apply_packed_fmt},
78
{PJMEDIA_FORMAT_BGRA, "BGRA", PJMEDIA_COLOR_MODEL_RGB, 32, 1, &apply_packed_fmt},
79
{PJMEDIA_FORMAT_DIB , "DIB ", PJMEDIA_COLOR_MODEL_RGB, 24, 1, &apply_packed_fmt},
80
{PJMEDIA_FORMAT_GBRP, "GBRP", PJMEDIA_COLOR_MODEL_RGB, 24, 3, &apply_planar_444},
81
{PJMEDIA_FORMAT_AYUV, "AYUV", PJMEDIA_COLOR_MODEL_YUV, 32, 1, &apply_packed_fmt},
82
{PJMEDIA_FORMAT_YUY2, "YUY2", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt},
83
{PJMEDIA_FORMAT_UYVY, "UYVY", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt},
84
{PJMEDIA_FORMAT_YVYU, "YVYU", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt},
85
{PJMEDIA_FORMAT_I420, "I420", PJMEDIA_COLOR_MODEL_YUV, 12, 3, &apply_planar_420},
86
{PJMEDIA_FORMAT_YV12, "YV12", PJMEDIA_COLOR_MODEL_YUV, 12, 3, &apply_planar_420},
87
{PJMEDIA_FORMAT_I422, "I422", PJMEDIA_COLOR_MODEL_YUV, 16, 3, &apply_planar_422},
88
{PJMEDIA_FORMAT_I420JPEG, "I420JPG", PJMEDIA_COLOR_MODEL_YUV, 12, 3, &apply_planar_420},
89
{PJMEDIA_FORMAT_I422JPEG, "I422JPG", PJMEDIA_COLOR_MODEL_YUV, 16, 3, &apply_planar_422},
92
PJ_DEF(void) pjmedia_format_init_video( pjmedia_format *fmt,
101
fmt->type = PJMEDIA_TYPE_VIDEO;
102
fmt->detail_type = PJMEDIA_FORMAT_DETAIL_VIDEO;
104
fmt->det.vid.size.w = width;
105
fmt->det.vid.size.h = height;
106
fmt->det.vid.fps.num = fps_num;
107
fmt->det.vid.fps.denum = fps_denum;
108
fmt->det.vid.avg_bps = fmt->det.vid.max_bps = 0;
110
if (pjmedia_video_format_mgr_instance()) {
111
const pjmedia_video_format_info *vfi;
112
pjmedia_video_apply_fmt_param vafp;
115
vfi = pjmedia_get_video_format_info(NULL, fmt->id);
117
pj_bzero(&vafp, sizeof(vafp));
118
vafp.size = fmt->det.vid.size;
119
vfi->apply_fmt(vfi, &vafp);
121
bps = (pj_uint32_t)vafp.framebytes * fps_num * (pj_size_t)8 / fps_denum;
122
fmt->det.vid.avg_bps = fmt->det.vid.max_bps = bps;
127
PJ_DEF(pjmedia_video_format_detail*)
128
pjmedia_format_get_video_format_detail(const pjmedia_format *fmt,
129
pj_bool_t assert_valid)
131
if (fmt->detail_type==PJMEDIA_FORMAT_DETAIL_VIDEO) {
132
return (pjmedia_video_format_detail*)&fmt->det.vid;
134
pj_assert(!assert_valid || !"Invalid video format detail");
140
static pj_status_t apply_packed_fmt(const pjmedia_video_format_info *fi,
141
pjmedia_video_apply_fmt_param *aparam)
146
stride = (pj_size_t)((aparam->size.w*fi->bpp) >> 3);
148
/* Calculate memsize */
149
aparam->framebytes = stride * aparam->size.h;
151
/* Packed formats only use 1 plane */
152
aparam->planes[0] = aparam->buffer;
153
aparam->strides[0] = (int)stride;
154
aparam->plane_bytes[0] = aparam->framebytes;
156
/* Zero unused planes */
157
for (i=1; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) {
158
aparam->strides[i] = 0;
159
aparam->planes[i] = NULL;
165
static pj_status_t apply_planar_420(const pjmedia_video_format_info *fi,
166
pjmedia_video_apply_fmt_param *aparam)
173
/* Calculate memsize */
174
Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h);
175
aparam->framebytes = Y_bytes + (Y_bytes>>1);
177
/* Planar formats use 3 plane */
178
aparam->strides[0] = aparam->size.w;
179
aparam->strides[1] = aparam->strides[2] = (aparam->size.w>>1);
181
aparam->planes[0] = aparam->buffer;
182
aparam->planes[1] = aparam->planes[0] + Y_bytes;
183
aparam->planes[2] = aparam->planes[1] + (Y_bytes>>2);
185
aparam->plane_bytes[0] = Y_bytes;
186
aparam->plane_bytes[1] = aparam->plane_bytes[2] = (Y_bytes>>2);
188
/* Zero unused planes */
189
for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) {
190
aparam->strides[i] = 0;
191
aparam->planes[i] = NULL;
192
aparam->plane_bytes[i] = 0;
198
static pj_status_t apply_planar_422(const pjmedia_video_format_info *fi,
199
pjmedia_video_apply_fmt_param *aparam)
206
/* Calculate memsize */
207
Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h);
208
aparam->framebytes = (Y_bytes << 1);
210
/* Planar formats use 3 plane */
211
aparam->strides[0] = aparam->size.w;
212
aparam->strides[1] = aparam->strides[2] = (aparam->size.w>>1);
214
aparam->planes[0] = aparam->buffer;
215
aparam->planes[1] = aparam->planes[0] + Y_bytes;
216
aparam->planes[2] = aparam->planes[1] + (Y_bytes>>1);
218
aparam->plane_bytes[0] = Y_bytes;
219
aparam->plane_bytes[1] = aparam->plane_bytes[2] = (Y_bytes>>1);
221
/* Zero unused planes */
222
for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) {
223
aparam->strides[i] = 0;
224
aparam->planes[i] = NULL;
225
aparam->plane_bytes[i] = 0;
231
static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi,
232
pjmedia_video_apply_fmt_param *aparam)
239
/* Calculate memsize */
240
Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h);
241
aparam->framebytes = (Y_bytes * 3);
243
/* Planar formats use 3 plane */
244
aparam->strides[0] = aparam->strides[1] =
245
aparam->strides[2] = aparam->size.w;
247
aparam->planes[0] = aparam->buffer;
248
aparam->planes[1] = aparam->planes[0] + Y_bytes;
249
aparam->planes[2] = aparam->planes[1] + Y_bytes;
251
aparam->plane_bytes[0] = aparam->plane_bytes[1] =
252
aparam->plane_bytes[2] = Y_bytes;
254
/* Zero unused planes */
255
for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) {
256
aparam->strides[i] = 0;
257
aparam->planes[i] = NULL;
258
aparam->plane_bytes[i] = 0;
265
pjmedia_video_format_mgr_create(pj_pool_t *pool,
268
pjmedia_video_format_mgr **p_mgr)
270
pjmedia_video_format_mgr *mgr;
273
PJ_ASSERT_RETURN(pool && options==0, PJ_EINVAL);
275
PJ_UNUSED_ARG(options);
277
mgr = PJ_POOL_ALLOC_T(pool, pjmedia_video_format_mgr);
278
mgr->max_info = max_fmt;
280
mgr->infos = pj_pool_calloc(pool, max_fmt, sizeof(pjmedia_video_format_info *));
282
if (video_format_mgr_instance == NULL)
283
video_format_mgr_instance = mgr;
285
for (i=0; i<PJ_ARRAY_SIZE(built_in_vid_fmt_info); ++i) {
286
pjmedia_register_video_format_info(mgr,
287
&built_in_vid_fmt_info[i]);
297
PJ_DEF(const pjmedia_video_format_info*)
298
pjmedia_get_video_format_info(pjmedia_video_format_mgr *mgr,
301
pjmedia_video_format_info **first;
305
mgr = pjmedia_video_format_mgr_instance();
307
PJ_ASSERT_RETURN(mgr != NULL, NULL);
309
/* Binary search for the appropriate format id */
310
first = &mgr->infos[0];
313
unsigned half = n / 2;
314
pjmedia_video_format_info **mid = first + half;
316
if ((*mid)->id < id) {
319
} else if ((*mid)->id==id) {
331
pjmedia_register_video_format_info(pjmedia_video_format_mgr *mgr,
332
pjmedia_video_format_info *info)
337
mgr = pjmedia_video_format_mgr_instance();
339
PJ_ASSERT_RETURN(mgr != NULL, PJ_EINVALIDOP);
341
if (mgr->info_cnt >= mgr->max_info)
344
/* Insert to the array, sorted */
345
for (i=0; i<mgr->info_cnt; ++i) {
346
if (mgr->infos[i]->id >= info->id)
350
if (i < mgr->info_cnt) {
351
if (mgr->infos[i]->id == info->id) {
353
mgr->infos[i] = info;
357
pj_memmove(&mgr->infos[i+1], &mgr->infos[i],
358
(mgr->info_cnt - i) * sizeof(pjmedia_video_format_info*));
361
mgr->infos[i] = info;
367
PJ_DEF(pjmedia_video_format_mgr*) pjmedia_video_format_mgr_instance(void)
369
pj_assert(video_format_mgr_instance != NULL);
370
return video_format_mgr_instance;
374
pjmedia_video_format_mgr_set_instance(pjmedia_video_format_mgr *mgr)
376
video_format_mgr_instance = mgr;
380
PJ_DEF(void) pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr *mgr)
383
mgr = pjmedia_video_format_mgr_instance();
385
PJ_ASSERT_ON_FAIL(mgr != NULL, return);
388
if (video_format_mgr_instance == mgr)
389
video_format_mgr_instance = NULL;
392
#endif /* PJMEDIA_HAS_VIDEO */