]> sjero.net Git - linphone/blob - linphone/mediastreamer2/src/msvideo.c
remote ortp and add it as a submodule instead.
[linphone] / linphone / mediastreamer2 / src / msvideo.c
1 /*
2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (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
20 #include "mediastreamer2/msvideo.h"
21
22 static void yuv_buf_init(YuvBuf *buf, int w, int h, uint8_t *ptr){
23         int ysize,usize;
24         ysize=w*h;
25         usize=ysize/4;
26         buf->w=w;
27         buf->h=h;
28         buf->planes[0]=ptr;
29         buf->planes[1]=buf->planes[0]+ysize;
30         buf->planes[2]=buf->planes[1]+usize;
31         buf->planes[3]=0;
32         buf->strides[0]=w;
33         buf->strides[1]=w/2;
34         buf->strides[2]=buf->strides[1];
35         buf->strides[3]=0;
36 }
37
38 int yuv_buf_init_from_mblk(YuvBuf *buf, mblk_t *m){
39         int size=m->b_wptr-m->b_rptr;
40         int w,h;
41         if (size==(MS_VIDEO_SIZE_QCIF_W*MS_VIDEO_SIZE_QCIF_H*3)/2){
42                 w=MS_VIDEO_SIZE_QCIF_W;
43                 h=MS_VIDEO_SIZE_QCIF_H;
44         }else if (size==(MS_VIDEO_SIZE_CIF_W*MS_VIDEO_SIZE_CIF_H*3)/2){
45                 w=MS_VIDEO_SIZE_CIF_W;
46                 h=MS_VIDEO_SIZE_CIF_H;
47         }else if (size==(MS_VIDEO_SIZE_QVGA_W*MS_VIDEO_SIZE_QVGA_H*3)/2){
48                 w=MS_VIDEO_SIZE_QVGA_W;
49                 h=MS_VIDEO_SIZE_QVGA_H;
50         }else if (size==(MS_VIDEO_SIZE_VGA_W*MS_VIDEO_SIZE_VGA_H*3)/2){
51                 w=MS_VIDEO_SIZE_VGA_W;
52                 h=MS_VIDEO_SIZE_VGA_H;
53         }else if (size==(MS_VIDEO_SIZE_4CIF_W*MS_VIDEO_SIZE_4CIF_H*3)/2){
54                 w=MS_VIDEO_SIZE_4CIF_W;
55                 h=MS_VIDEO_SIZE_4CIF_H;
56         }else if (size==(MS_VIDEO_SIZE_SVGA_W*MS_VIDEO_SIZE_SVGA_H*3)/2){
57                 w=MS_VIDEO_SIZE_SVGA_W;
58                 h=MS_VIDEO_SIZE_SVGA_H;
59         }else if (size==(MS_VIDEO_SIZE_SQCIF_W*MS_VIDEO_SIZE_SQCIF_H*3)/2){
60                 w=MS_VIDEO_SIZE_SQCIF_W;
61                 h=MS_VIDEO_SIZE_SQCIF_H;
62         }else if (size==(MS_VIDEO_SIZE_QQVGA_W*MS_VIDEO_SIZE_QQVGA_H*3)/2){
63                 w=MS_VIDEO_SIZE_QQVGA_W;
64                 h=MS_VIDEO_SIZE_QQVGA_H;
65         }else if (size==(MS_VIDEO_SIZE_NS1_W*MS_VIDEO_SIZE_NS1_H*3)/2){
66                 w=MS_VIDEO_SIZE_NS1_W;
67                 h=MS_VIDEO_SIZE_NS1_H;
68         }else if (size==(MS_VIDEO_SIZE_QSIF_W*MS_VIDEO_SIZE_QSIF_H*3)/2){
69                 w=MS_VIDEO_SIZE_QSIF_W;
70                 h=MS_VIDEO_SIZE_QSIF_H;
71         }else if (size==(MS_VIDEO_SIZE_SIF_W*MS_VIDEO_SIZE_SIF_H*3)/2){
72                 w=MS_VIDEO_SIZE_SIF_W;
73                 h=MS_VIDEO_SIZE_SIF_H;
74         }else if (size==(MS_VIDEO_SIZE_4SIF_W*MS_VIDEO_SIZE_4SIF_H*3)/2){
75                 w=MS_VIDEO_SIZE_4SIF_W;
76                 h=MS_VIDEO_SIZE_4SIF_H;
77         }else if (size==(MS_VIDEO_SIZE_288P_W*MS_VIDEO_SIZE_288P_H*3)/2){
78                 w=MS_VIDEO_SIZE_288P_W;
79                 h=MS_VIDEO_SIZE_288P_H;
80         }else if (size==(MS_VIDEO_SIZE_448P_W*MS_VIDEO_SIZE_448P_H*3)/2){
81                 w=MS_VIDEO_SIZE_448P_W;
82                 h=MS_VIDEO_SIZE_448P_H;
83         }else if (size==(MS_VIDEO_SIZE_576P_W*MS_VIDEO_SIZE_576P_H*3)/2){
84                 w=MS_VIDEO_SIZE_576P_W;
85                 h=MS_VIDEO_SIZE_576P_H;
86         }else if (size==(MS_VIDEO_SIZE_720P_W*MS_VIDEO_SIZE_720P_H*3)/2){
87                 w=MS_VIDEO_SIZE_720P_W;
88                 h=MS_VIDEO_SIZE_720P_H;
89         }else if (size==(MS_VIDEO_SIZE_1080P_W*MS_VIDEO_SIZE_1080P_H*3)/2){
90                 w=MS_VIDEO_SIZE_1080P_W;
91                 h=MS_VIDEO_SIZE_1080P_H;
92         }else if (size==(MS_VIDEO_SIZE_SDTV_W*MS_VIDEO_SIZE_SDTV_H*3)/2){
93                 w=MS_VIDEO_SIZE_SDTV_W;
94                 h=MS_VIDEO_SIZE_SDTV_H;
95         }else if (size==(MS_VIDEO_SIZE_HDTVP_W*MS_VIDEO_SIZE_HDTVP_H*3)/2){
96                 w=MS_VIDEO_SIZE_HDTVP_W;
97                 h=MS_VIDEO_SIZE_HDTVP_H;
98         }else if (size==(MS_VIDEO_SIZE_XGA_W*MS_VIDEO_SIZE_XGA_H*3)/2){
99                 w=MS_VIDEO_SIZE_XGA_W;
100                 h=MS_VIDEO_SIZE_XGA_H;
101         }else if (size==(MS_VIDEO_SIZE_WXGA_W*MS_VIDEO_SIZE_WXGA_H*3)/2){
102                 w=MS_VIDEO_SIZE_WXGA_W;
103                 h=MS_VIDEO_SIZE_WXGA_H;
104         }else if (size==(160*112*3)/2){/*format used by econf*/
105                 w=160;
106                 h=112;
107         }else if (size==(320*200*3)/2){/*format used by gTalk */
108                 w=320;
109                 h=200;
110         }else {
111                 ms_error("Unsupported image size: size=%i (bug somewhere !)",size);
112                 return -1;
113         }
114         yuv_buf_init(buf,w,h,m->b_rptr);
115         return 0;
116 }
117
118 void yuv_buf_init_from_mblk_with_size(YuvBuf *buf, mblk_t *m, int w, int h){
119         yuv_buf_init(buf,w,h,m->b_rptr);
120 }
121
122 mblk_t * yuv_buf_alloc(YuvBuf *buf, int w, int h){
123         int size=(w*h*3)/2;
124         mblk_t *msg=allocb(size,0);
125         yuv_buf_init(buf,w,h,msg->b_wptr);
126         msg->b_wptr+=size;
127         return msg;
128 }
129
130 static void plane_copy(const uint8_t *src_plane, int src_stride,
131         uint8_t *dst_plane, int dst_stride, MSVideoSize roi){
132         int i;
133         for(i=0;i<roi.height;++i){
134                 memcpy(dst_plane,src_plane,roi.width);
135                 src_plane+=src_stride;
136                 dst_plane+=dst_stride;
137         }
138 }
139
140 void yuv_buf_copy(uint8_t *src_planes[], const int src_strides[], 
141                 uint8_t *dst_planes[], const int dst_strides[3], MSVideoSize roi){
142         plane_copy(src_planes[0],src_strides[0],dst_planes[0],dst_strides[0],roi);
143         roi.width=roi.width/2;
144         roi.height=roi.height/2;
145         plane_copy(src_planes[1],src_strides[1],dst_planes[1],dst_strides[1],roi);
146         plane_copy(src_planes[2],src_strides[2],dst_planes[2],dst_strides[2],roi);
147 }
148
149 static void plane_mirror(uint8_t *p, int linesize, int w, int h){
150         int i,j;
151         uint8_t tmp;
152         for(j=0;j<h;++j){
153                 for(i=0;i<w/2;++i){
154                         tmp=p[i];
155                         p[i]=p[w-1-i];
156                         p[w-1-i]=tmp;
157                 }
158                 p+=linesize;
159         }
160 }
161
162 /*in place mirroring*/
163 void yuv_buf_mirror(YuvBuf *buf){
164         plane_mirror(buf->planes[0],buf->strides[0],buf->w,buf->h);
165         plane_mirror(buf->planes[1],buf->strides[1],buf->w/2,buf->h/2);
166         plane_mirror(buf->planes[2],buf->strides[2],buf->w/2,buf->h/2);
167 }
168
169 #ifndef MAKEFOURCC
170 #define MAKEFOURCC(a,b,c,d) ((d)<<24 | (c)<<16 | (b)<<8 | (a))
171 #endif
172
173 MSPixFmt ms_fourcc_to_pix_fmt(uint32_t fourcc){
174         MSPixFmt ret;
175         switch (fourcc){
176                 case MAKEFOURCC('I','4','2','0'):
177                         ret=MS_YUV420P;
178                 break;
179                 case MAKEFOURCC('Y','U','Y','2'):
180                         ret=MS_YUY2;
181                 break;
182                 case MAKEFOURCC('Y','U','Y','V'):
183                         ret=MS_YUYV;
184                 break;
185                 case MAKEFOURCC('U','Y','V','Y'):
186                         ret=MS_UYVY;
187                 break;
188                 case 0: /*BI_RGB on windows*/
189                         ret=MS_RGB24;
190                 break;
191                 default:
192                         ret=MS_PIX_FMT_UNKNOWN;
193         }
194         return ret;
195 }
196
197 void rgb24_revert(uint8_t *buf, int w, int h, int linesize){
198         uint8_t *p,*pe;
199         int i,j;
200         uint8_t *end=buf+((h-1)*linesize);
201         uint8_t exch;
202         p=buf;
203         pe=end-1;
204         for(i=0;i<h/2;++i){
205                 for(j=0;j<w*3;++j){
206                         exch=p[i];
207                         p[i]=pe[-i];
208                         pe[-i]=exch;
209                 }
210                 p+=linesize;
211                 pe-=linesize;
212         }       
213 }
214
215 void rgb24_copy_revert(uint8_t *dstbuf, int dstlsz,
216                                 const uint8_t *srcbuf, int srclsz, MSVideoSize roi){
217         int i,j;
218         const uint8_t *psrc;
219         uint8_t *pdst;
220         psrc=srcbuf;
221         pdst=dstbuf+(dstlsz*(roi.height-1));
222         for(i=0;i<roi.height;++i){
223                 for(j=0;j<roi.width*3;++j){
224                         pdst[(roi.width*3)-1-j]=psrc[j];
225                 }
226                 pdst-=dstlsz;
227                 psrc+=srclsz;
228         }
229 }
230
231 static MSVideoSize _ordered_vsizes[]={
232         {MS_VIDEO_SIZE_QCIF_W,MS_VIDEO_SIZE_QCIF_H},
233         {MS_VIDEO_SIZE_QVGA_W,MS_VIDEO_SIZE_QVGA_H},
234         {MS_VIDEO_SIZE_CIF_W,MS_VIDEO_SIZE_CIF_H},
235         {MS_VIDEO_SIZE_VGA_W,MS_VIDEO_SIZE_VGA_H},
236         {MS_VIDEO_SIZE_4CIF_W,MS_VIDEO_SIZE_4CIF_H},
237         {MS_VIDEO_SIZE_720P_W,MS_VIDEO_SIZE_720P_H},
238         {0,0}
239 };
240
241 MSVideoSize ms_video_size_get_just_lower_than(MSVideoSize vs){
242         MSVideoSize *p;
243         MSVideoSize ret;
244         ret.width=0;
245         ret.height=0;
246         for(p=_ordered_vsizes;p->width!=0;++p){
247                 if (ms_video_size_greater_than(vs,*p) && !ms_video_size_equal(vs,*p)){
248                         ret=*p;
249                 }else return ret;
250         }
251         return ret;
252 };