source: mediastreamer2/linphone/mediastreamer2/src/sizeconv.c @ 205:f65852271c00

Last change on this file since 205:f65852271c00 was 205:f65852271c00, checked in by smorlat <smorlat@…>, 5 years ago

internationalization of mediastreamer2 (thanks to Petr Pisar)

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@208 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 5.7 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#ifdef HAVE_CONFIG_H
21#include "mediastreamer-config.h"
22#endif
23
24#include "mediastreamer2/msfilter.h"
25#include "mediastreamer2/msticker.h"
26#include "mediastreamer2/msvideo.h"
27
28#include "ffmpeg-priv.h"
29
30typedef struct SizeConvState{
31        MSVideoSize target_vsize;
32        MSVideoSize in_vsize;
33        YuvBuf outbuf;
34        struct SwsContext *sws_ctx;
35        mblk_t *om;
36        float fps;
37        float start_time;
38        int frame_count;
39        queue_t rq;
40} SizeConvState;
41
42
43/*this MSFilter will do on the fly picture size conversion. It attempts to guess the picture size from the yuv buffer size. YUV420P is assumed on input.
44For now it only supports QCIF->CIF, QVGA->CIF and CIF->CIF (does nothing in this case)*/
45
46static void size_conv_init(MSFilter *f){
47        SizeConvState *s=(SizeConvState *)ms_new(SizeConvState,1);
48        s->target_vsize.width = MS_VIDEO_SIZE_CIF_W;
49        s->target_vsize.height = MS_VIDEO_SIZE_CIF_H;
50        s->in_vsize.width=0;
51        s->in_vsize.height=0;
52        s->sws_ctx=NULL;
53        s->om=NULL;
54        s->start_time=0;
55        s->frame_count=-1;
56        s->fps=-1; /* default to process ALL frames */
57        qinit(&s->rq);
58        f->data=s;
59}
60
61static void size_conv_uninit(MSFilter *f){
62        SizeConvState *s=(SizeConvState*)f->data;
63        ms_free(s);
64}
65
66static void size_conv_postprocess(MSFilter *f){
67        SizeConvState *s=(SizeConvState*)f->data;
68        if (s->sws_ctx!=NULL) {
69                sws_freeContext(s->sws_ctx);
70                s->sws_ctx=NULL;
71        }
72        if (s->om!=NULL){
73                freemsg(s->om);
74                s->om=NULL;
75        }
76        flushq(&s->rq,0);
77  s->frame_count=-1;
78}
79
80static mblk_t *size_conv_alloc_mblk(SizeConvState *s){
81        if (s->om!=NULL){
82                int ref=s->om->b_datap->db_ref;
83                if (ref==1){
84                        return dupmsg(s->om);
85                }else{
86                        /*the last msg is still referenced by somebody else*/
87                        ms_message("size_conv_alloc_mblk: Somebody still retaining yuv buffer (ref=%i)",ref);
88                        freemsg(s->om);
89                        s->om=NULL;
90                }
91        }
92        s->om=yuv_buf_alloc(&s->outbuf,s->target_vsize.width,s->target_vsize.height);
93        return dupmsg(s->om);
94}
95
96static struct SwsContext * get_resampler(SizeConvState *s, int w, int h){
97        if (s->in_vsize.width!=w ||
98                s->in_vsize.height!=h || s->sws_ctx==NULL){
99                if (s->sws_ctx!=NULL){
100                        sws_freeContext(s->sws_ctx);
101                        s->sws_ctx=NULL;
102                }
103                s->sws_ctx=sws_getContext(w,h,PIX_FMT_YUV420P,
104                        s->target_vsize.width,s->target_vsize.height,PIX_FMT_YUV420P,
105                        SWS_FAST_BILINEAR,NULL, NULL, NULL);
106                s->in_vsize.width=w;
107                s->in_vsize.height=h;
108        }
109        return s->sws_ctx;
110}
111
112static void size_conv_process(MSFilter *f){
113        SizeConvState *s=(SizeConvState*)f->data;
114        YuvBuf inbuf;
115        mblk_t *im;
116        int cur_frame;
117
118        ms_filter_lock(f);
119
120        if (s->frame_count==-1){
121                s->start_time=f->ticker->time;
122                s->frame_count=0;
123        }
124        while((im=ms_queue_get(f->inputs[0]))!=NULL ){
125                putq(&s->rq, im);
126        }
127
128        cur_frame=((f->ticker->time-s->start_time)*s->fps/1000.0);
129        if (cur_frame<=s->frame_count && s->fps>=0) {
130                /* too much frame */
131                while(s->rq.q_mcount>1){
132                        ms_message("MSSizeConv: extra frame removed.");
133                        im=getq(&s->rq);
134                        freemsg(im);
135                }
136                ms_filter_unlock(f);
137                return;
138        }
139
140        if (cur_frame>s->frame_count && s->fps>=0) {
141                /*keep the most recent frame if several frames have been captured */
142                while(s->rq.q_mcount>1){
143                        ms_message("MSSizeConv: extra frame removed.");
144                        im=getq(&s->rq);
145                        freemsg(im);
146                }
147        }
148        while((im=getq(&s->rq))!=NULL ){
149                if (yuv_buf_init_from_mblk(&inbuf,im)==0){
150                        if (inbuf.w==s->target_vsize.width &&
151                                inbuf.h==s->target_vsize.height){
152                                ms_queue_put(f->outputs[0],im);
153                        }else{
154                                struct SwsContext *sws_ctx=get_resampler(s,inbuf.w,inbuf.h);
155                                mblk_t *om=size_conv_alloc_mblk(s);
156                                if (sws_scale(sws_ctx,inbuf.planes,inbuf.strides, 0,
157                                        inbuf.h, s->outbuf.planes, s->outbuf.strides)<0){
158                                        ms_error("MSSizeConv: error in sws_scale().");
159                                }
160                                ms_queue_put(f->outputs[0],om);
161                                freemsg(im);
162                        }
163                        s->frame_count++;
164                }else freemsg(im);
165        }
166
167        ms_filter_unlock(f);
168}
169
170
171static int sizeconv_set_vsize(MSFilter *f, void*arg){
172        SizeConvState *s=(SizeConvState*)f->data;
173        ms_filter_lock(f);
174        s->target_vsize=*(MSVideoSize*)arg;
175        freemsg(s->om);
176        s->om=NULL;
177        if (s->sws_ctx!=NULL) {
178                sws_freeContext(s->sws_ctx);
179                s->sws_ctx=NULL;
180        }
181        ms_filter_unlock(f);
182        return 0;
183}
184
185static int sizeconv_set_fps(MSFilter *f, void *arg){
186        SizeConvState *s=(SizeConvState*)f->data;
187        s->fps=*((float*)arg);
188        s->frame_count=-1; /* reset counter used for fps */
189        return 0;
190}
191
192
193static MSFilterMethod methods[]={
194        {       MS_FILTER_SET_FPS       ,       sizeconv_set_fps        },
195        {       MS_FILTER_SET_VIDEO_SIZE, sizeconv_set_vsize    },
196        {       0       ,       NULL }
197};
198
199#ifdef _MSC_VER
200
201MSFilterDesc ms_size_conv_desc={
202        MS_SIZE_CONV_ID,
203        "MSSizeConv",
204        N_("A video size converter"),
205        MS_FILTER_OTHER,
206        NULL,
207        1,
208        1,
209        size_conv_init,
210        NULL,
211        size_conv_process,
212        size_conv_postprocess,
213        size_conv_uninit,
214        methods
215};
216
217#else
218
219MSFilterDesc ms_size_conv_desc={
220        .id=MS_SIZE_CONV_ID,
221        .name="MSSizeConv",
222        .text=N_("a small video size converter"),
223        .ninputs=1,
224        .noutputs=1,
225        .init=size_conv_init,
226        .process=size_conv_process,
227        .postprocess=size_conv_postprocess,
228        .uninit=size_conv_uninit,
229        .methods=methods
230};
231
232#endif
233
234MS_FILTER_DESC_EXPORT(ms_size_conv_desc)
235
Note: See TracBrowser for help on using the repository browser.