blob: f74b12699eb8b3c2420449aa7dd699ff539108c3 [file] [log] [blame]
Alexandre Lision67916dd2014-01-24 13:33:04 -05001/* $Id$ */
2/*
3 * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pjmedia/converter.h>
20#include <pj/errno.h>
21
22#if PJMEDIA_HAS_LIBSWSCALE && PJMEDIA_HAS_LIBAVUTIL
23
24#include "ffmpeg_util.h"
25#include <libswscale/swscale.h>
26
27static pj_status_t factory_create_converter(pjmedia_converter_factory *cf,
28 pj_pool_t *pool,
29 const pjmedia_conversion_param*prm,
30 pjmedia_converter **p_cv);
31static void factory_destroy_factory(pjmedia_converter_factory *cf);
32static pj_status_t libswscale_conv_convert(pjmedia_converter *converter,
33 pjmedia_frame *src_frame,
34 pjmedia_frame *dst_frame);
35static void libswscale_conv_destroy(pjmedia_converter *converter);
36
37
38struct fmt_info
39{
40 const pjmedia_video_format_info *fmt_info;
41 pjmedia_video_apply_fmt_param apply_param;
42};
43
44struct ffmpeg_converter
45{
46 pjmedia_converter base;
47 struct SwsContext *sws_ctx;
48 struct fmt_info src,
49 dst;
50};
51
52static pjmedia_converter_factory_op libswscale_factory_op =
53{
54 &factory_create_converter,
55 &factory_destroy_factory
56};
57
58static pjmedia_converter_op liswscale_converter_op =
59{
60 &libswscale_conv_convert,
61 &libswscale_conv_destroy
62};
63
64static pj_status_t factory_create_converter(pjmedia_converter_factory *cf,
65 pj_pool_t *pool,
66 const pjmedia_conversion_param *prm,
67 pjmedia_converter **p_cv)
68{
69 enum PixelFormat srcFormat, dstFormat;
70 const pjmedia_video_format_detail *src_detail, *dst_detail;
71 const pjmedia_video_format_info *src_fmt_info, *dst_fmt_info;
72 struct SwsContext *sws_ctx;
73 struct ffmpeg_converter *fcv;
74 pj_status_t status;
75
76 PJ_UNUSED_ARG(cf);
77
78 /* Only supports video */
79 if (prm->src.type != PJMEDIA_TYPE_VIDEO ||
80 prm->dst.type != prm->src.type ||
81 prm->src.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO ||
82 prm->dst.detail_type != prm->src.detail_type)
83 {
84 return PJ_ENOTSUP;
85 }
86
87 /* lookup source format info */
88 src_fmt_info = pjmedia_get_video_format_info(
89 pjmedia_video_format_mgr_instance(),
90 prm->src.id);
91 if (!src_fmt_info)
92 return PJ_ENOTSUP;
93
94 /* lookup destination format info */
95 dst_fmt_info = pjmedia_get_video_format_info(
96 pjmedia_video_format_mgr_instance(),
97 prm->dst.id);
98 if (!dst_fmt_info)
99 return PJ_ENOTSUP;
100
101 src_detail = pjmedia_format_get_video_format_detail(&prm->src, PJ_TRUE);
102 dst_detail = pjmedia_format_get_video_format_detail(&prm->dst, PJ_TRUE);
103
104 status = pjmedia_format_id_to_PixelFormat(prm->src.id, &srcFormat);
105 if (status != PJ_SUCCESS)
106 return PJ_ENOTSUP;
107
108 status = pjmedia_format_id_to_PixelFormat(prm->dst.id, &dstFormat);
109 if (status != PJ_SUCCESS)
110 return PJ_ENOTSUP;
111
112 sws_ctx = sws_getContext(src_detail->size.w, src_detail->size.h, srcFormat,
113 dst_detail->size.w, dst_detail->size.h, dstFormat,
114 SWS_BICUBIC,
115 NULL, NULL, NULL);
116 if (sws_ctx == NULL)
117 return PJ_ENOTSUP;
118
119 fcv = PJ_POOL_ZALLOC_T(pool, struct ffmpeg_converter);
120 fcv->base.op = &liswscale_converter_op;
121 fcv->sws_ctx = sws_ctx;
122 fcv->src.apply_param.size = src_detail->size;
123 fcv->src.fmt_info = src_fmt_info;
124 fcv->dst.apply_param.size = dst_detail->size;
125 fcv->dst.fmt_info = dst_fmt_info;
126
127 *p_cv = &fcv->base;
128
129 return PJ_SUCCESS;
130}
131
132static void factory_destroy_factory(pjmedia_converter_factory *cf)
133{
134 PJ_UNUSED_ARG(cf);
135}
136
137static pj_status_t libswscale_conv_convert(pjmedia_converter *converter,
138 pjmedia_frame *src_frame,
139 pjmedia_frame *dst_frame)
140{
141 struct ffmpeg_converter *fcv = (struct ffmpeg_converter*)converter;
142 struct fmt_info *src = &fcv->src,
143 *dst = &fcv->dst;
144 int h;
145
146 src->apply_param.buffer = src_frame->buf;
147 (*src->fmt_info->apply_fmt)(src->fmt_info, &src->apply_param);
148
149 dst->apply_param.buffer = dst_frame->buf;
150 (*dst->fmt_info->apply_fmt)(dst->fmt_info, &dst->apply_param);
151
152 h = sws_scale(fcv->sws_ctx,
153 (const uint8_t* const *)src->apply_param.planes,
154 src->apply_param.strides,
155 0, src->apply_param.size.h,
156 dst->apply_param.planes, dst->apply_param.strides);
157
158 //sws_scale() return value can't be trusted? There are cases when
159 //sws_scale() returns zero but conversion seems to work okay.
160 //return h==(int)dst->apply_param.size.h ? PJ_SUCCESS : PJ_EUNKNOWN;
161 PJ_UNUSED_ARG(h);
162
163 return PJ_SUCCESS;
164}
165
166static void libswscale_conv_destroy(pjmedia_converter *converter)
167{
168 struct ffmpeg_converter *fcv = (struct ffmpeg_converter*)converter;
169 if (fcv->sws_ctx) {
170 struct SwsContext *tmp = fcv->sws_ctx;
171 fcv->sws_ctx = NULL;
172 sws_freeContext(tmp);
173 }
174}
175
176static pjmedia_converter_factory libswscale_factory =
177{
178 NULL, NULL, /* list */
179 "libswscale", /* name */
180 PJMEDIA_CONVERTER_PRIORITY_NORMAL+1, /* priority */
181 NULL /* op will be init-ed later */
182};
183
184PJ_DEF(pj_status_t)
185pjmedia_libswscale_converter_init(pjmedia_converter_mgr *mgr)
186{
187 libswscale_factory.op = &libswscale_factory_op;
188 pjmedia_ffmpeg_add_ref();
189 return pjmedia_converter_mgr_register_factory(mgr, &libswscale_factory);
190}
191
192
193PJ_DEF(pj_status_t)
194pjmedia_libswscale_converter_shutdown(pjmedia_converter_mgr *mgr,
195 pj_pool_t *pool)
196{
197 PJ_UNUSED_ARG(pool);
198 pjmedia_ffmpeg_dec_ref();
199 return pjmedia_converter_mgr_unregister_factory(mgr, &libswscale_factory,
200 PJ_TRUE);
201}
202
203#ifdef _MSC_VER
204# pragma comment( lib, "avutil.lib")
205# pragma comment( lib, "swscale.lib")
206#endif
207
208#endif /* #if PJMEDIA_HAS_LIBSWSCALE && PJMEDIA_HAS_LIBAVUTIL */