diff options
author | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
---|---|---|
committer | David M. Lee <dlee@digium.com> | 2013-01-07 14:24:28 -0600 |
commit | f3ab456a17af1c89a6e3be4d20c5944853df1cb0 (patch) | |
tree | d00e1a332cd038a6d906a1ea0ac91e1a4458e617 /pjmedia/src/pjmedia/format.c |
Import pjproject-2.0.1
Diffstat (limited to 'pjmedia/src/pjmedia/format.c')
-rw-r--r-- | pjmedia/src/pjmedia/format.c | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/pjmedia/src/pjmedia/format.c b/pjmedia/src/pjmedia/format.c new file mode 100644 index 0000000..5e1d253 --- /dev/null +++ b/pjmedia/src/pjmedia/format.c @@ -0,0 +1,416 @@ +/* $Id: format.c 4158 2012-06-06 09:56:14Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <pjmedia/format.h> +#include <pj/assert.h> +#include <pj/errno.h> +#include <pj/pool.h> +#include <pj/string.h> + + +PJ_DEF(void) pjmedia_format_init_audio( pjmedia_format *fmt, + pj_uint32_t fmt_id, + unsigned clock_rate, + unsigned channel_count, + unsigned bits_per_sample, + unsigned frame_time_usec, + pj_uint32_t avg_bps, + pj_uint32_t max_bps) +{ + fmt->id = fmt_id; + fmt->type = PJMEDIA_TYPE_AUDIO; + fmt->detail_type = PJMEDIA_FORMAT_DETAIL_AUDIO; + + fmt->det.aud.clock_rate = clock_rate; + fmt->det.aud.channel_count = channel_count; + fmt->det.aud.bits_per_sample = bits_per_sample; + fmt->det.aud.frame_time_usec = frame_time_usec; + fmt->det.aud.avg_bps = avg_bps; + fmt->det.aud.max_bps = max_bps; +} + + +PJ_DEF(pjmedia_audio_format_detail*) +pjmedia_format_get_audio_format_detail(const pjmedia_format *fmt, + pj_bool_t assert_valid) +{ + if (fmt->detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO) { + return (pjmedia_audio_format_detail*) &fmt->det.aud; + } else { + /* Get rid of unused var compiler warning if pj_assert() + * macro does not do anything + */ + PJ_UNUSED_ARG(assert_valid); + pj_assert(!assert_valid || !"Invalid audio format detail"); + return NULL; + } +} + + +PJ_DEF(pjmedia_format*) pjmedia_format_copy(pjmedia_format *dst, + const pjmedia_format *src) +{ + return (pjmedia_format*)pj_memcpy(dst, src, sizeof(*src)); +} + + +#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) + + +static pj_status_t apply_packed_fmt(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam); + +static pj_status_t apply_planar_420(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam); + +static pj_status_t apply_planar_422(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam); + +static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam); + +struct pjmedia_video_format_mgr +{ + unsigned max_info; + unsigned info_cnt; + pjmedia_video_format_info **infos; +}; + +static pjmedia_video_format_mgr *video_format_mgr_instance; +static pjmedia_video_format_info built_in_vid_fmt_info[] = +{ + {PJMEDIA_FORMAT_RGB24, "RGB24", PJMEDIA_COLOR_MODEL_RGB, 24, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_RGBA, "RGBA", PJMEDIA_COLOR_MODEL_RGB, 32, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_BGRA, "BGRA", PJMEDIA_COLOR_MODEL_RGB, 32, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_DIB , "DIB ", PJMEDIA_COLOR_MODEL_RGB, 24, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_GBRP, "GBRP", PJMEDIA_COLOR_MODEL_RGB, 24, 3, &apply_planar_444}, + {PJMEDIA_FORMAT_AYUV, "AYUV", PJMEDIA_COLOR_MODEL_YUV, 32, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_YUY2, "YUY2", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_UYVY, "UYVY", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_YVYU, "YVYU", PJMEDIA_COLOR_MODEL_YUV, 16, 1, &apply_packed_fmt}, + {PJMEDIA_FORMAT_I420, "I420", PJMEDIA_COLOR_MODEL_YUV, 12, 3, &apply_planar_420}, + {PJMEDIA_FORMAT_YV12, "YV12", PJMEDIA_COLOR_MODEL_YUV, 12, 3, &apply_planar_420}, + {PJMEDIA_FORMAT_I422, "I422", PJMEDIA_COLOR_MODEL_YUV, 16, 3, &apply_planar_422}, + {PJMEDIA_FORMAT_I420JPEG, "I420JPG", PJMEDIA_COLOR_MODEL_YUV, 12, 3, &apply_planar_420}, + {PJMEDIA_FORMAT_I422JPEG, "I422JPG", PJMEDIA_COLOR_MODEL_YUV, 16, 3, &apply_planar_422}, +}; + +PJ_DEF(void) pjmedia_format_init_video( pjmedia_format *fmt, + pj_uint32_t fmt_id, + unsigned width, + unsigned height, + unsigned fps_num, + unsigned fps_denum) +{ + pj_assert(fps_denum); + fmt->id = fmt_id; + fmt->type = PJMEDIA_TYPE_VIDEO; + fmt->detail_type = PJMEDIA_FORMAT_DETAIL_VIDEO; + + fmt->det.vid.size.w = width; + fmt->det.vid.size.h = height; + fmt->det.vid.fps.num = fps_num; + fmt->det.vid.fps.denum = fps_denum; + fmt->det.vid.avg_bps = fmt->det.vid.max_bps = 0; + + if (pjmedia_video_format_mgr_instance()) { + const pjmedia_video_format_info *vfi; + pjmedia_video_apply_fmt_param vafp; + pj_uint32_t bps; + + vfi = pjmedia_get_video_format_info(NULL, fmt->id); + if (vfi) { + pj_bzero(&vafp, sizeof(vafp)); + vafp.size = fmt->det.vid.size; + vfi->apply_fmt(vfi, &vafp); + + bps = vafp.framebytes * fps_num * (pj_size_t)8 / fps_denum; + fmt->det.vid.avg_bps = fmt->det.vid.max_bps = bps; + } + } +} + +PJ_DEF(pjmedia_video_format_detail*) +pjmedia_format_get_video_format_detail(const pjmedia_format *fmt, + pj_bool_t assert_valid) +{ + if (fmt->detail_type==PJMEDIA_FORMAT_DETAIL_VIDEO) { + return (pjmedia_video_format_detail*)&fmt->det.vid; + } else { + pj_assert(!assert_valid || !"Invalid video format detail"); + return NULL; + } +} + + +static pj_status_t apply_packed_fmt(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam) +{ + unsigned i; + pj_size_t stride; + + stride = (pj_size_t)((aparam->size.w*fi->bpp) >> 3); + + /* Calculate memsize */ + aparam->framebytes = stride * aparam->size.h; + + /* Packed formats only use 1 plane */ + aparam->planes[0] = aparam->buffer; + aparam->strides[0] = stride; + aparam->plane_bytes[0] = aparam->framebytes; + + /* Zero unused planes */ + for (i=1; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) { + aparam->strides[i] = 0; + aparam->planes[i] = NULL; + } + + return PJ_SUCCESS; +} + +static pj_status_t apply_planar_420(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam) +{ + unsigned i; + pj_size_t Y_bytes; + + PJ_UNUSED_ARG(fi); + + /* Calculate memsize */ + Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h); + aparam->framebytes = Y_bytes + (Y_bytes>>1); + + /* Planar formats use 3 plane */ + aparam->strides[0] = aparam->size.w; + aparam->strides[1] = aparam->strides[2] = (aparam->size.w>>1); + + aparam->planes[0] = aparam->buffer; + aparam->planes[1] = aparam->planes[0] + Y_bytes; + aparam->planes[2] = aparam->planes[1] + (Y_bytes>>2); + + aparam->plane_bytes[0] = Y_bytes; + aparam->plane_bytes[1] = aparam->plane_bytes[2] = (Y_bytes>>2); + + /* Zero unused planes */ + for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) { + aparam->strides[i] = 0; + aparam->planes[i] = NULL; + aparam->plane_bytes[i] = 0; + } + + return PJ_SUCCESS; +} + +static pj_status_t apply_planar_422(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam) +{ + unsigned i; + pj_size_t Y_bytes; + + PJ_UNUSED_ARG(fi); + + /* Calculate memsize */ + Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h); + aparam->framebytes = (Y_bytes << 1); + + /* Planar formats use 3 plane */ + aparam->strides[0] = aparam->size.w; + aparam->strides[1] = aparam->strides[2] = (aparam->size.w>>1); + + aparam->planes[0] = aparam->buffer; + aparam->planes[1] = aparam->planes[0] + Y_bytes; + aparam->planes[2] = aparam->planes[1] + (Y_bytes>>1); + + aparam->plane_bytes[0] = Y_bytes; + aparam->plane_bytes[1] = aparam->plane_bytes[2] = (Y_bytes>>1); + + /* Zero unused planes */ + for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) { + aparam->strides[i] = 0; + aparam->planes[i] = NULL; + aparam->plane_bytes[i] = 0; + } + + return PJ_SUCCESS; +} + +static pj_status_t apply_planar_444(const pjmedia_video_format_info *fi, + pjmedia_video_apply_fmt_param *aparam) +{ + unsigned i; + pj_size_t Y_bytes; + + PJ_UNUSED_ARG(fi); + + /* Calculate memsize */ + Y_bytes = (pj_size_t)(aparam->size.w * aparam->size.h); + aparam->framebytes = (Y_bytes * 3); + + /* Planar formats use 3 plane */ + aparam->strides[0] = aparam->strides[1] = + aparam->strides[2] = aparam->size.w; + + aparam->planes[0] = aparam->buffer; + aparam->planes[1] = aparam->planes[0] + Y_bytes; + aparam->planes[2] = aparam->planes[1] + Y_bytes; + + aparam->plane_bytes[0] = aparam->plane_bytes[1] = + aparam->plane_bytes[2] = Y_bytes; + + /* Zero unused planes */ + for (i=3; i<PJMEDIA_MAX_VIDEO_PLANES; ++i) { + aparam->strides[i] = 0; + aparam->planes[i] = NULL; + aparam->plane_bytes[i] = 0; + } + + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) +pjmedia_video_format_mgr_create(pj_pool_t *pool, + unsigned max_fmt, + unsigned options, + pjmedia_video_format_mgr **p_mgr) +{ + pjmedia_video_format_mgr *mgr; + unsigned i; + + PJ_ASSERT_RETURN(pool && options==0, PJ_EINVAL); + + PJ_UNUSED_ARG(options); + + mgr = PJ_POOL_ALLOC_T(pool, pjmedia_video_format_mgr); + mgr->max_info = max_fmt; + mgr->info_cnt = 0; + mgr->infos = pj_pool_calloc(pool, max_fmt, sizeof(pjmedia_video_format_info *)); + + if (video_format_mgr_instance == NULL) + video_format_mgr_instance = mgr; + + for (i=0; i<PJ_ARRAY_SIZE(built_in_vid_fmt_info); ++i) { + pjmedia_register_video_format_info(mgr, + &built_in_vid_fmt_info[i]); + } + + if (p_mgr) + *p_mgr = mgr; + + return PJ_SUCCESS; +} + + +PJ_DEF(const pjmedia_video_format_info*) +pjmedia_get_video_format_info(pjmedia_video_format_mgr *mgr, + pj_uint32_t id) +{ + pjmedia_video_format_info **first; + int comp; + unsigned n; + + if (!mgr) + mgr = pjmedia_video_format_mgr_instance(); + + PJ_ASSERT_RETURN(mgr != NULL, NULL); + + /* Binary search for the appropriate format id */ + comp = -1; + first = &mgr->infos[0]; + n = mgr->info_cnt; + for (; n > 0; ) { + unsigned half = n / 2; + pjmedia_video_format_info **mid = first + half; + + if ((*mid)->id < id) { + first = ++mid; + n -= half + 1; + } else if ((*mid)->id==id) { + return *mid; + } else { + n = half; + } + } + + return NULL; +} + + +PJ_DEF(pj_status_t) +pjmedia_register_video_format_info(pjmedia_video_format_mgr *mgr, + pjmedia_video_format_info *info) +{ + unsigned i; + + if (!mgr) + mgr = pjmedia_video_format_mgr_instance(); + + PJ_ASSERT_RETURN(mgr != NULL, PJ_EINVALIDOP); + + if (mgr->info_cnt >= mgr->max_info) + return PJ_ETOOMANY; + + /* Insert to the array, sorted */ + for (i=0; i<mgr->info_cnt; ++i) { + if (mgr->infos[i]->id >= info->id) + break; + } + + if (i < mgr->info_cnt) { + if (mgr->infos[i]->id == info->id) { + /* just overwrite */ + mgr->infos[i] = info; + return PJ_SUCCESS; + } + + pj_memmove(&mgr->infos[i+1], &mgr->infos[i], + (mgr->info_cnt - i) * sizeof(pjmedia_video_format_info*)); + } + + mgr->infos[i] = info; + mgr->info_cnt++; + + return PJ_SUCCESS; +} + +PJ_DEF(pjmedia_video_format_mgr*) pjmedia_video_format_mgr_instance(void) +{ + pj_assert(video_format_mgr_instance != NULL); + return video_format_mgr_instance; +} + +PJ_DEF(void) +pjmedia_video_format_mgr_set_instance(pjmedia_video_format_mgr *mgr) +{ + video_format_mgr_instance = mgr; +} + + +PJ_DEF(void) pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr *mgr) +{ + if (!mgr) + mgr = pjmedia_video_format_mgr_instance(); + + PJ_ASSERT_ON_FAIL(mgr != NULL, return); + + mgr->info_cnt = 0; + if (video_format_mgr_instance == mgr) + video_format_mgr_instance = NULL; +} + +#endif /* PJMEDIA_HAS_VIDEO */ |