ffmpeg / libavfilter / vf_mp.c @ 61d7f8fe
History | View | Annotate | Download (30.7 KB)
1 |
/*
|
---|---|
2 |
* Copyright (c) 2011 Michael Niedermayer
|
3 |
*
|
4 |
* This file is part of FFmpeg.
|
5 |
*
|
6 |
* FFmpeg 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.
|
10 |
*
|
11 |
* FFmpeg 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.
|
15 |
*
|
16 |
* You should have received a copy of the GNU General Public License
|
17 |
* along with FFmpeg; if not, write to the Free Software
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
19 |
*
|
20 |
* Parts of this file have been stolen from mplayer
|
21 |
*/
|
22 |
|
23 |
/**
|
24 |
* @file
|
25 |
*/
|
26 |
|
27 |
#include "avfilter.h" |
28 |
#include "libavutil/avassert.h" |
29 |
#include "libavutil/pixdesc.h" |
30 |
#include "libavutil/intreadwrite.h" |
31 |
#include "libavcore/imgutils.h" |
32 |
|
33 |
#include "libmpcodecs/vf.h" |
34 |
#include "libmpcodecs/img_format.h" |
35 |
#include "libmpcodecs/cpudetect.h" |
36 |
#include "libmpcodecs/vd_ffmpeg.h" |
37 |
#include "libmpcodecs/vf_scale.h" |
38 |
#include "libmpcodecs/libvo/fastmemcpy.h" |
39 |
|
40 |
#include "libswscale/swscale.h" |
41 |
|
42 |
|
43 |
//FIXME maybe link the orig in
|
44 |
static const struct { |
45 |
int fmt;
|
46 |
enum PixelFormat pix_fmt;
|
47 |
} conversion_map[] = { |
48 |
{IMGFMT_ARGB, PIX_FMT_ARGB}, |
49 |
{IMGFMT_BGRA, PIX_FMT_BGRA}, |
50 |
{IMGFMT_BGR24, PIX_FMT_BGR24}, |
51 |
{IMGFMT_BGR16BE, PIX_FMT_RGB565BE}, |
52 |
{IMGFMT_BGR16LE, PIX_FMT_RGB565LE}, |
53 |
{IMGFMT_BGR15BE, PIX_FMT_RGB555BE}, |
54 |
{IMGFMT_BGR15LE, PIX_FMT_RGB555LE}, |
55 |
{IMGFMT_BGR12BE, PIX_FMT_RGB444BE}, |
56 |
{IMGFMT_BGR12LE, PIX_FMT_RGB444LE}, |
57 |
{IMGFMT_BGR8, PIX_FMT_RGB8}, |
58 |
{IMGFMT_BGR4, PIX_FMT_RGB4}, |
59 |
{IMGFMT_BGR1, PIX_FMT_MONOBLACK}, |
60 |
{IMGFMT_RGB1, PIX_FMT_MONOBLACK}, |
61 |
{IMGFMT_RG4B, PIX_FMT_BGR4_BYTE}, |
62 |
{IMGFMT_BG4B, PIX_FMT_RGB4_BYTE}, |
63 |
{IMGFMT_RGB48LE, PIX_FMT_RGB48LE}, |
64 |
{IMGFMT_RGB48BE, PIX_FMT_RGB48BE}, |
65 |
{IMGFMT_ABGR, PIX_FMT_ABGR}, |
66 |
{IMGFMT_RGBA, PIX_FMT_RGBA}, |
67 |
{IMGFMT_RGB24, PIX_FMT_RGB24}, |
68 |
{IMGFMT_RGB16BE, PIX_FMT_BGR565BE}, |
69 |
{IMGFMT_RGB16LE, PIX_FMT_BGR565LE}, |
70 |
{IMGFMT_RGB15BE, PIX_FMT_BGR555BE}, |
71 |
{IMGFMT_RGB15LE, PIX_FMT_BGR555LE}, |
72 |
{IMGFMT_RGB12BE, PIX_FMT_BGR444BE}, |
73 |
{IMGFMT_RGB12LE, PIX_FMT_BGR444LE}, |
74 |
{IMGFMT_RGB8, PIX_FMT_BGR8}, |
75 |
{IMGFMT_RGB4, PIX_FMT_BGR4}, |
76 |
{IMGFMT_BGR8, PIX_FMT_PAL8}, |
77 |
{IMGFMT_YUY2, PIX_FMT_YUYV422}, |
78 |
{IMGFMT_UYVY, PIX_FMT_UYVY422}, |
79 |
{IMGFMT_NV12, PIX_FMT_NV12}, |
80 |
{IMGFMT_NV21, PIX_FMT_NV21}, |
81 |
{IMGFMT_Y800, PIX_FMT_GRAY8}, |
82 |
{IMGFMT_Y8, PIX_FMT_GRAY8}, |
83 |
{IMGFMT_YVU9, PIX_FMT_YUV410P}, |
84 |
{IMGFMT_IF09, PIX_FMT_YUV410P}, |
85 |
{IMGFMT_YV12, PIX_FMT_YUV420P}, |
86 |
{IMGFMT_I420, PIX_FMT_YUV420P}, |
87 |
{IMGFMT_IYUV, PIX_FMT_YUV420P}, |
88 |
{IMGFMT_411P, PIX_FMT_YUV411P}, |
89 |
{IMGFMT_422P, PIX_FMT_YUV422P}, |
90 |
{IMGFMT_444P, PIX_FMT_YUV444P}, |
91 |
{IMGFMT_440P, PIX_FMT_YUV440P}, |
92 |
|
93 |
{IMGFMT_420A, PIX_FMT_YUVA420P}, |
94 |
|
95 |
{IMGFMT_420P16_LE, PIX_FMT_YUV420P16LE}, |
96 |
{IMGFMT_420P16_BE, PIX_FMT_YUV420P16BE}, |
97 |
{IMGFMT_422P16_LE, PIX_FMT_YUV422P16LE}, |
98 |
{IMGFMT_422P16_BE, PIX_FMT_YUV422P16BE}, |
99 |
{IMGFMT_444P16_LE, PIX_FMT_YUV444P16LE}, |
100 |
{IMGFMT_444P16_BE, PIX_FMT_YUV444P16BE}, |
101 |
|
102 |
// YUVJ are YUV formats that use the full Y range and not just
|
103 |
// 16 - 235 (see colorspaces.txt).
|
104 |
// Currently they are all treated the same way.
|
105 |
{IMGFMT_YV12, PIX_FMT_YUVJ420P}, |
106 |
{IMGFMT_422P, PIX_FMT_YUVJ422P}, |
107 |
{IMGFMT_444P, PIX_FMT_YUVJ444P}, |
108 |
{IMGFMT_440P, PIX_FMT_YUVJ440P}, |
109 |
|
110 |
{IMGFMT_XVMC_MOCO_MPEG2, PIX_FMT_XVMC_MPEG2_MC}, |
111 |
{IMGFMT_XVMC_IDCT_MPEG2, PIX_FMT_XVMC_MPEG2_IDCT}, |
112 |
{IMGFMT_VDPAU_MPEG1, PIX_FMT_VDPAU_MPEG1}, |
113 |
{IMGFMT_VDPAU_MPEG2, PIX_FMT_VDPAU_MPEG2}, |
114 |
{IMGFMT_VDPAU_H264, PIX_FMT_VDPAU_H264}, |
115 |
{IMGFMT_VDPAU_WMV3, PIX_FMT_VDPAU_WMV3}, |
116 |
{IMGFMT_VDPAU_VC1, PIX_FMT_VDPAU_VC1}, |
117 |
{IMGFMT_VDPAU_MPEG4, PIX_FMT_VDPAU_MPEG4}, |
118 |
{0, PIX_FMT_NONE}
|
119 |
}; |
120 |
|
121 |
//copied from vf.c
|
122 |
extern const vf_info_t vf_info_vo; |
123 |
extern const vf_info_t vf_info_rectangle; |
124 |
extern const vf_info_t vf_info_bmovl; |
125 |
extern const vf_info_t vf_info_crop; |
126 |
extern const vf_info_t vf_info_expand; |
127 |
extern const vf_info_t vf_info_pp; |
128 |
extern const vf_info_t vf_info_scale; |
129 |
extern const vf_info_t vf_info_format; |
130 |
extern const vf_info_t vf_info_noformat; |
131 |
extern const vf_info_t vf_info_flip; |
132 |
extern const vf_info_t vf_info_rotate; |
133 |
extern const vf_info_t vf_info_mirror; |
134 |
extern const vf_info_t vf_info_palette; |
135 |
extern const vf_info_t vf_info_lavc; |
136 |
extern const vf_info_t vf_info_zrmjpeg; |
137 |
extern const vf_info_t vf_info_dvbscale; |
138 |
extern const vf_info_t vf_info_cropdetect; |
139 |
extern const vf_info_t vf_info_test; |
140 |
extern const vf_info_t vf_info_noise; |
141 |
extern const vf_info_t vf_info_yvu9; |
142 |
extern const vf_info_t vf_info_lavcdeint; |
143 |
extern const vf_info_t vf_info_eq; |
144 |
extern const vf_info_t vf_info_eq2; |
145 |
extern const vf_info_t vf_info_gradfun; |
146 |
extern const vf_info_t vf_info_halfpack; |
147 |
extern const vf_info_t vf_info_dint; |
148 |
extern const vf_info_t vf_info_1bpp; |
149 |
extern const vf_info_t vf_info_2xsai; |
150 |
extern const vf_info_t vf_info_unsharp; |
151 |
extern const vf_info_t vf_info_swapuv; |
152 |
extern const vf_info_t vf_info_il; |
153 |
extern const vf_info_t vf_info_fil; |
154 |
extern const vf_info_t vf_info_boxblur; |
155 |
extern const vf_info_t vf_info_sab; |
156 |
extern const vf_info_t vf_info_smartblur; |
157 |
extern const vf_info_t vf_info_perspective; |
158 |
extern const vf_info_t vf_info_down3dright; |
159 |
extern const vf_info_t vf_info_field; |
160 |
extern const vf_info_t vf_info_denoise3d; |
161 |
extern const vf_info_t vf_info_hqdn3d; |
162 |
extern const vf_info_t vf_info_detc; |
163 |
extern const vf_info_t vf_info_telecine; |
164 |
extern const vf_info_t vf_info_tinterlace; |
165 |
extern const vf_info_t vf_info_tfields; |
166 |
extern const vf_info_t vf_info_ivtc; |
167 |
extern const vf_info_t vf_info_ilpack; |
168 |
extern const vf_info_t vf_info_dsize; |
169 |
extern const vf_info_t vf_info_decimate; |
170 |
extern const vf_info_t vf_info_softpulldown; |
171 |
extern const vf_info_t vf_info_pullup; |
172 |
extern const vf_info_t vf_info_filmdint; |
173 |
extern const vf_info_t vf_info_framestep; |
174 |
extern const vf_info_t vf_info_tile; |
175 |
extern const vf_info_t vf_info_delogo; |
176 |
extern const vf_info_t vf_info_remove_logo; |
177 |
extern const vf_info_t vf_info_hue; |
178 |
extern const vf_info_t vf_info_spp; |
179 |
extern const vf_info_t vf_info_uspp; |
180 |
extern const vf_info_t vf_info_fspp; |
181 |
extern const vf_info_t vf_info_pp7; |
182 |
extern const vf_info_t vf_info_yuvcsp; |
183 |
extern const vf_info_t vf_info_kerndeint; |
184 |
extern const vf_info_t vf_info_rgbtest; |
185 |
extern const vf_info_t vf_info_qp; |
186 |
extern const vf_info_t vf_info_phase; |
187 |
extern const vf_info_t vf_info_divtc; |
188 |
extern const vf_info_t vf_info_harddup; |
189 |
extern const vf_info_t vf_info_softskip; |
190 |
extern const vf_info_t vf_info_screenshot; |
191 |
extern const vf_info_t vf_info_ass; |
192 |
extern const vf_info_t vf_info_mcdeint; |
193 |
extern const vf_info_t vf_info_yadif; |
194 |
extern const vf_info_t vf_info_blackframe; |
195 |
extern const vf_info_t vf_info_geq; |
196 |
extern const vf_info_t vf_info_ow; |
197 |
extern const vf_info_t vf_info_fixpts; |
198 |
extern const vf_info_t vf_info_stereo3d; |
199 |
|
200 |
|
201 |
static const vf_info_t* const filters[]={ |
202 |
&vf_info_2xsai, |
203 |
&vf_info_blackframe, |
204 |
&vf_info_boxblur, |
205 |
&vf_info_cropdetect, |
206 |
&vf_info_decimate, |
207 |
&vf_info_delogo, |
208 |
&vf_info_denoise3d, |
209 |
&vf_info_detc, |
210 |
&vf_info_dint, |
211 |
&vf_info_divtc, |
212 |
&vf_info_down3dright, |
213 |
&vf_info_dsize, |
214 |
&vf_info_eq2, |
215 |
&vf_info_eq, |
216 |
&vf_info_field, |
217 |
&vf_info_fil, |
218 |
// &vf_info_filmdint, cmmx.h vd.h ‘opt_screen_size_x’
|
219 |
&vf_info_fixpts, |
220 |
&vf_info_framestep, |
221 |
&vf_info_fspp, |
222 |
&vf_info_geq, |
223 |
&vf_info_gradfun, |
224 |
&vf_info_harddup, |
225 |
&vf_info_hqdn3d, |
226 |
&vf_info_hue, |
227 |
&vf_info_il, |
228 |
&vf_info_ilpack, |
229 |
&vf_info_ivtc, |
230 |
&vf_info_kerndeint, |
231 |
&vf_info_mcdeint, |
232 |
&vf_info_mirror, |
233 |
&vf_info_noise, |
234 |
&vf_info_ow, |
235 |
&vf_info_palette, |
236 |
&vf_info_perspective, |
237 |
&vf_info_phase, |
238 |
&vf_info_pp7, |
239 |
&vf_info_pullup, |
240 |
&vf_info_qp, |
241 |
&vf_info_rectangle, |
242 |
&vf_info_remove_logo, |
243 |
&vf_info_rgbtest, |
244 |
&vf_info_rotate, |
245 |
&vf_info_sab, |
246 |
&vf_info_screenshot, |
247 |
&vf_info_smartblur, |
248 |
&vf_info_softpulldown, |
249 |
&vf_info_softskip, |
250 |
&vf_info_spp, |
251 |
&vf_info_swapuv, |
252 |
&vf_info_telecine, |
253 |
&vf_info_test, |
254 |
&vf_info_tile, |
255 |
&vf_info_tinterlace, |
256 |
&vf_info_unsharp, |
257 |
&vf_info_uspp, |
258 |
&vf_info_yuvcsp, |
259 |
&vf_info_yvu9, |
260 |
|
261 |
NULL
|
262 |
}; |
263 |
|
264 |
/*
|
265 |
Unsupported filters
|
266 |
1bpp
|
267 |
ass
|
268 |
bmovl
|
269 |
crop
|
270 |
dvbscale
|
271 |
flip
|
272 |
expand
|
273 |
format
|
274 |
halfpack
|
275 |
lavc
|
276 |
lavcdeint
|
277 |
noformat
|
278 |
pp
|
279 |
scale
|
280 |
stereo3d
|
281 |
tfields
|
282 |
vo
|
283 |
yadif
|
284 |
zrmjpeg
|
285 |
*/
|
286 |
|
287 |
CpuCaps gCpuCaps; //FIXME initialize this so optims work
|
288 |
|
289 |
|
290 |
//exact copy from vf_scale.c
|
291 |
int get_sws_cpuflags(void){ |
292 |
return
|
293 |
(gCpuCaps.hasMMX ? SWS_CPU_CAPS_MMX : 0)
|
294 |
| (gCpuCaps.hasMMX2 ? SWS_CPU_CAPS_MMX2 : 0)
|
295 |
| (gCpuCaps.has3DNow ? SWS_CPU_CAPS_3DNOW : 0)
|
296 |
| (gCpuCaps.hasAltiVec ? SWS_CPU_CAPS_ALTIVEC : 0);
|
297 |
} |
298 |
|
299 |
static void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, SwsFilter **dstFilterParam) |
300 |
{ |
301 |
static int firstTime=1; |
302 |
*flags=0;
|
303 |
|
304 |
#if ARCH_X86
|
305 |
if(gCpuCaps.hasMMX)
|
306 |
__asm__ volatile("emms\n\t"::: "memory"); //FIXME this should not be required but it IS (even for non-MMX versions) |
307 |
#endif
|
308 |
if(firstTime)
|
309 |
{ |
310 |
firstTime=0;
|
311 |
*flags= SWS_PRINT_INFO; |
312 |
} |
313 |
else if( mp_msg_test(MSGT_VFILTER,MSGL_DBG2) ) *flags= SWS_PRINT_INFO; |
314 |
|
315 |
switch(SWS_BILINEAR)
|
316 |
{ |
317 |
case 0: *flags|= SWS_FAST_BILINEAR; break; |
318 |
case 1: *flags|= SWS_BILINEAR; break; |
319 |
case 2: *flags|= SWS_BICUBIC; break; |
320 |
case 3: *flags|= SWS_X; break; |
321 |
case 4: *flags|= SWS_POINT; break; |
322 |
case 5: *flags|= SWS_AREA; break; |
323 |
case 6: *flags|= SWS_BICUBLIN; break; |
324 |
case 7: *flags|= SWS_GAUSS; break; |
325 |
case 8: *flags|= SWS_SINC; break; |
326 |
case 9: *flags|= SWS_LANCZOS; break; |
327 |
case 10:*flags|= SWS_SPLINE; break; |
328 |
default:*flags|= SWS_BILINEAR; break; |
329 |
} |
330 |
|
331 |
*srcFilterParam= NULL;
|
332 |
*dstFilterParam= NULL;
|
333 |
} |
334 |
|
335 |
//exact copy from vf_scale.c
|
336 |
// will use sws_flags & src_filter (from cmd line)
|
337 |
struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat) |
338 |
{ |
339 |
int flags, i;
|
340 |
SwsFilter *dstFilterParam, *srcFilterParam; |
341 |
enum PixelFormat dfmt, sfmt;
|
342 |
|
343 |
for(i=0; conversion_map[i].fmt && dstFormat != conversion_map[i].fmt; i++); |
344 |
dfmt= conversion_map[i].pix_fmt; |
345 |
for(i=0; conversion_map[i].fmt && srcFormat != conversion_map[i].fmt; i++); |
346 |
sfmt= conversion_map[i].pix_fmt; |
347 |
|
348 |
if (srcFormat == IMGFMT_RGB8 || srcFormat == IMGFMT_BGR8) sfmt = PIX_FMT_PAL8;
|
349 |
sws_getFlagsAndFilterFromCmdLine(&flags, &srcFilterParam, &dstFilterParam); |
350 |
|
351 |
return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags | get_sws_cpuflags(), srcFilterParam, dstFilterParam, NULL); |
352 |
} |
353 |
|
354 |
typedef struct { |
355 |
vf_instance_t vf; |
356 |
vf_instance_t next_vf; |
357 |
AVFilterContext *avfctx; |
358 |
int frame_returned;
|
359 |
} MPContext; |
360 |
|
361 |
void mp_msg(int mod, int lev, const char *format, ... ){ |
362 |
va_list va; |
363 |
va_start(va, format); |
364 |
//FIXME convert lev/mod
|
365 |
av_vlog(NULL, AV_LOG_DEBUG, format, va);
|
366 |
va_end(va); |
367 |
} |
368 |
|
369 |
int mp_msg_test(int mod, int lev){ |
370 |
return 123; |
371 |
} |
372 |
|
373 |
void init_avcodec(void) |
374 |
{ |
375 |
//we maybe should init but its kinda 1. unneeded 2. a bit inpolite from here
|
376 |
} |
377 |
|
378 |
//Exact copy of vf.c
|
379 |
void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
|
380 |
dst->pict_type= src->pict_type; |
381 |
dst->fields = src->fields; |
382 |
dst->qscale_type= src->qscale_type; |
383 |
if(dst->width == src->width && dst->height == src->height){
|
384 |
dst->qstride= src->qstride; |
385 |
dst->qscale= src->qscale; |
386 |
} |
387 |
} |
388 |
|
389 |
//Exact copy of vf.c
|
390 |
void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){ |
391 |
if (vf->next->draw_slice) {
|
392 |
vf->next->draw_slice(vf->next,src,stride,w,h,x,y); |
393 |
return;
|
394 |
} |
395 |
if (!vf->dmpi) {
|
396 |
mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
|
397 |
return;
|
398 |
} |
399 |
if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
|
400 |
memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x, |
401 |
src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]); |
402 |
return;
|
403 |
} |
404 |
memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0], |
405 |
w, h, vf->dmpi->stride[0], stride[0]); |
406 |
memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift), |
407 |
src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]); |
408 |
memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift), |
409 |
src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]); |
410 |
} |
411 |
|
412 |
//Exact copy of vf.c
|
413 |
void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){ |
414 |
int y;
|
415 |
if(mpi->flags&MP_IMGFLAG_PLANAR){
|
416 |
y0&=~1;h+=h&1; |
417 |
if(x0==0 && w==mpi->width){ |
418 |
// full width clear:
|
419 |
memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h); |
420 |
memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift)); |
421 |
memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift)); |
422 |
} else
|
423 |
for(y=y0;y<y0+h;y+=2){ |
424 |
memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w); |
425 |
memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w); |
426 |
memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift)); |
427 |
memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift)); |
428 |
} |
429 |
return;
|
430 |
} |
431 |
// packed:
|
432 |
for(y=y0;y<y0+h;y++){
|
433 |
unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0; |
434 |
if(mpi->flags&MP_IMGFLAG_YUV){
|
435 |
unsigned int* p=(unsigned int*) dst; |
436 |
int size=(mpi->bpp>>3)*w/4; |
437 |
int i;
|
438 |
#if HAVE_BIGENDIAN
|
439 |
#define CLEAR_PACKEDYUV_PATTERN 0x00800080 |
440 |
#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000 |
441 |
#else
|
442 |
#define CLEAR_PACKEDYUV_PATTERN 0x80008000 |
443 |
#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080 |
444 |
#endif
|
445 |
if(mpi->flags&MP_IMGFLAG_SWAPPED){
|
446 |
for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED; |
447 |
for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
|
448 |
} else {
|
449 |
for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN; |
450 |
for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
|
451 |
} |
452 |
} else
|
453 |
memset(dst,0,(mpi->bpp>>3)*w); |
454 |
} |
455 |
} |
456 |
|
457 |
int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){ |
458 |
return 1; |
459 |
} |
460 |
|
461 |
//used by delogo
|
462 |
unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){ |
463 |
return preferred;
|
464 |
} |
465 |
|
466 |
mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){ |
467 |
MPContext *m= ((uint8_t*)vf) - offsetof(MPContext, next_vf); |
468 |
mp_image_t* mpi=NULL;
|
469 |
int w2;
|
470 |
int number = mp_imgtype >> 16; |
471 |
|
472 |
av_assert0(vf->next == NULL); // all existing filters call this just on next |
473 |
|
474 |
//vf_dint needs these as it calls vf_get_image() before configuring the output
|
475 |
if(vf->w==0 && w>0) vf->w=w; |
476 |
if(vf->h==0 && h>0) vf->h=h; |
477 |
|
478 |
av_assert0(w == -1 || w >= vf->w);
|
479 |
av_assert0(h == -1 || h >= vf->h);
|
480 |
av_assert0(vf->w > 0);
|
481 |
av_assert0(vf->h > 0);
|
482 |
|
483 |
av_log(m->avfctx, AV_LOG_DEBUG, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
|
484 |
|
485 |
if (w == -1) w = vf->w; |
486 |
if (h == -1) h = vf->h; |
487 |
|
488 |
w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w; |
489 |
|
490 |
// Note: we should call libvo first to check if it supports direct rendering
|
491 |
// and if not, then fallback to software buffers:
|
492 |
switch(mp_imgtype & 0xff){ |
493 |
case MP_IMGTYPE_EXPORT:
|
494 |
if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h); |
495 |
mpi=vf->imgctx.export_images[0];
|
496 |
break;
|
497 |
case MP_IMGTYPE_STATIC:
|
498 |
if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h); |
499 |
mpi=vf->imgctx.static_images[0];
|
500 |
break;
|
501 |
case MP_IMGTYPE_TEMP:
|
502 |
if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h); |
503 |
mpi=vf->imgctx.temp_images[0];
|
504 |
break;
|
505 |
case MP_IMGTYPE_IPB:
|
506 |
if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame: |
507 |
if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h); |
508 |
mpi=vf->imgctx.temp_images[0];
|
509 |
break;
|
510 |
} |
511 |
case MP_IMGTYPE_IP:
|
512 |
if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
|
513 |
mpi=vf->imgctx.static_images[vf->imgctx.static_idx]; |
514 |
vf->imgctx.static_idx^=1;
|
515 |
break;
|
516 |
case MP_IMGTYPE_NUMBERED:
|
517 |
if (number == -1) { |
518 |
int i;
|
519 |
for (i = 0; i < NUM_NUMBERED_MPI; i++) |
520 |
if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
|
521 |
break;
|
522 |
number = i; |
523 |
} |
524 |
if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL; |
525 |
if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
|
526 |
mpi = vf->imgctx.numbered_images[number]; |
527 |
mpi->number = number; |
528 |
break;
|
529 |
} |
530 |
if(mpi){
|
531 |
mpi->type=mp_imgtype; |
532 |
mpi->w=vf->w; mpi->h=vf->h; |
533 |
// keep buffer allocation status & color flags only:
|
534 |
// mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
|
535 |
mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS; |
536 |
// accept restrictions, draw_slice and palette flags only:
|
537 |
mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE); |
538 |
if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
|
539 |
if(mpi->width!=w2 || mpi->height!=h){
|
540 |
// printf("vf.c: MPI parameters changed! %dx%d -> %dx%d \n", mpi->width,mpi->height,w2,h);
|
541 |
if(mpi->flags&MP_IMGFLAG_ALLOCATED){
|
542 |
if(mpi->width<w2 || mpi->height<h){
|
543 |
// need to re-allocate buffer memory:
|
544 |
av_free(mpi->planes[0]);
|
545 |
mpi->flags&=~MP_IMGFLAG_ALLOCATED; |
546 |
mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
|
547 |
} |
548 |
// } else {
|
549 |
} { |
550 |
mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift; |
551 |
mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift; |
552 |
} |
553 |
} |
554 |
if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
|
555 |
if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
|
556 |
|
557 |
av_assert0(!vf->get_image); |
558 |
// check libvo first!
|
559 |
if(vf->get_image) vf->get_image(vf,mpi);
|
560 |
|
561 |
if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
|
562 |
// non-direct and not yet allocated image. allocate it!
|
563 |
if (!mpi->bpp) { // no way we can allocate this |
564 |
mp_msg(MSGT_DECVIDEO, MSGL_FATAL, |
565 |
"vf_get_image: Tried to allocate a format that can not be allocated!\n");
|
566 |
return NULL; |
567 |
} |
568 |
|
569 |
// check if codec prefer aligned stride:
|
570 |
if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
|
571 |
int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
|
572 |
mpi->flags&MP_IMGFLAG_YUV) ? |
573 |
(8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME |
574 |
w2=((w+align)&(~align)); |
575 |
if(mpi->width!=w2){
|
576 |
#if 0
|
577 |
// we have to change width... check if we CAN co it:
|
578 |
int flags=vf->query_format(vf,outfmt); // should not fail
|
579 |
if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
|
580 |
// printf("query -> 0x%X \n",flags);
|
581 |
if(flags&VFCAP_ACCEPT_STRIDE){
|
582 |
#endif
|
583 |
mpi->width=w2; |
584 |
mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift; |
585 |
// }
|
586 |
} |
587 |
} |
588 |
|
589 |
mp_image_alloc_planes(mpi); |
590 |
// printf("clearing img!\n");
|
591 |
vf_mpi_clear(mpi,0,0,mpi->width,mpi->height); |
592 |
} |
593 |
} |
594 |
av_assert0(!vf->start_slice); |
595 |
if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
|
596 |
if(vf->start_slice) vf->start_slice(vf,mpi);
|
597 |
if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
|
598 |
mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
|
599 |
"NULL"/*vf->info->name*/, |
600 |
(mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
|
601 |
((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"), |
602 |
(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"", |
603 |
mpi->width,mpi->height,mpi->bpp, |
604 |
(mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"), |
605 |
(mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed", |
606 |
mpi->bpp*mpi->width*mpi->height/8);
|
607 |
mp_msg(MSGT_DECVIDEO,MSGL_DBG2,"(imgfmt: %x, planes: %p,%p,%p strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n",
|
608 |
mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2], |
609 |
mpi->stride[0], mpi->stride[1], mpi->stride[2], |
610 |
mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift); |
611 |
mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED; |
612 |
} |
613 |
|
614 |
mpi->qscale = NULL;
|
615 |
} |
616 |
mpi->usage_count++; |
617 |
// printf("\rVF_MPI: %p %p %p %d %d %d \n",
|
618 |
// mpi->planes[0],mpi->planes[1],mpi->planes[2],
|
619 |
// mpi->stride[0],mpi->stride[1],mpi->stride[2]);
|
620 |
return mpi;
|
621 |
} |
622 |
|
623 |
|
624 |
int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){ |
625 |
MPContext *m= (void*)vf;
|
626 |
AVFilterLink *outlink = m->avfctx->outputs[0];
|
627 |
AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer));
|
628 |
AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
|
629 |
int i;
|
630 |
|
631 |
av_assert0(vf->next); |
632 |
|
633 |
av_log(m->avfctx, AV_LOG_DEBUG, "vf_next_put_image\n");
|
634 |
|
635 |
if (!pic || !picref)
|
636 |
goto fail;
|
637 |
|
638 |
picref->buf = pic; |
639 |
picref->buf->please_use_av_free= av_free; |
640 |
if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps)))) |
641 |
goto fail;
|
642 |
|
643 |
pic->w = picref->video->w = mpi->w; |
644 |
pic->h = picref->video->h = mpi->h; |
645 |
|
646 |
/* make sure the buffer gets read permission or it's useless for output */
|
647 |
picref->perms = AV_PERM_READ | AV_PERM_REUSE2; |
648 |
// av_assert0(mpi->flags&MP_IMGFLAG_READABLE);
|
649 |
if(!(mpi->flags&MP_IMGFLAG_PRESERVE))
|
650 |
picref->perms |= AV_PERM_WRITE; |
651 |
|
652 |
pic->refcount = 1;
|
653 |
picref->type = AVMEDIA_TYPE_VIDEO; |
654 |
|
655 |
for(i=0; conversion_map[i].fmt && mpi->imgfmt != conversion_map[i].fmt; i++); |
656 |
pic->format = picref->format = conversion_map[i].pix_fmt; |
657 |
|
658 |
memcpy(pic->data, mpi->planes, FFMIN(sizeof(pic->data) , sizeof(mpi->planes))); |
659 |
memcpy(pic->linesize, mpi->stride, FFMIN(sizeof(pic->linesize), sizeof(mpi->stride))); |
660 |
memcpy(picref->data, pic->data, sizeof(picref->data));
|
661 |
memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
|
662 |
|
663 |
if(pts != MP_NOPTS_VALUE)
|
664 |
picref->pts= pts * av_q2d(outlink->time_base); |
665 |
|
666 |
avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
|
667 |
avfilter_draw_slice(outlink, 0, picref->video->h, 1); |
668 |
avfilter_end_frame(outlink); |
669 |
avfilter_unref_buffer(picref); |
670 |
m->frame_returned++; |
671 |
|
672 |
return 1; |
673 |
fail:
|
674 |
if (picref && picref->video)
|
675 |
av_free(picref->video); |
676 |
av_free(picref); |
677 |
av_free(pic); |
678 |
return 0; |
679 |
} |
680 |
|
681 |
int vf_next_config(struct vf_instance *vf, |
682 |
int width, int height, int d_width, int d_height, |
683 |
unsigned int voflags, unsigned int outfmt){ |
684 |
|
685 |
av_assert0(width>0 && height>0); |
686 |
vf->next->w = width; vf->next->h = height; |
687 |
|
688 |
return 1; |
689 |
#if 0
|
690 |
int flags=vf->next->query_format(vf->next,outfmt);
|
691 |
if(!flags){
|
692 |
// hmm. colorspace mismatch!!!
|
693 |
//this is fatal for us ATM
|
694 |
return 0;
|
695 |
}
|
696 |
mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X req=0x%X \n",flags,vf->default_reqs);
|
697 |
miss=vf->default_reqs - (flags&vf->default_reqs);
|
698 |
if(miss&VFCAP_ACCEPT_STRIDE){
|
699 |
// vf requires stride support but vf->next doesn't support it!
|
700 |
// let's insert the 'expand' filter, it does the job for us:
|
701 |
vf_instance_t* vf2=vf_open_filter(vf->next,"expand",NULL);
|
702 |
if(!vf2) return 0; // shouldn't happen!
|
703 |
vf->next=vf2;
|
704 |
}
|
705 |
vf->next->w = width; vf->next->h = height;
|
706 |
#endif
|
707 |
return 1; |
708 |
} |
709 |
|
710 |
int vf_next_control(struct vf_instance *vf, int request, void* data){ |
711 |
MPContext *m= (void*)vf;
|
712 |
av_log(m->avfctx, AV_LOG_DEBUG, "Received control %d\n", request);
|
713 |
return 0; |
714 |
} |
715 |
|
716 |
static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){ |
717 |
MPContext *m= (void*)vf;
|
718 |
int i;
|
719 |
av_log(m->avfctx, AV_LOG_DEBUG, "query %X\n", fmt);
|
720 |
|
721 |
for(i=0; conversion_map[i].fmt; i++){ |
722 |
if(fmt==conversion_map[i].fmt)
|
723 |
return 1; //we suport all |
724 |
} |
725 |
return 0; |
726 |
} |
727 |
|
728 |
|
729 |
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
730 |
{ |
731 |
MPContext *m = ctx->priv; |
732 |
char name[256]; |
733 |
int i;
|
734 |
|
735 |
av_log(ctx, AV_LOG_WARNING, |
736 |
"This is a unholy filter, it will be purified by the ffmpeg exorcist team\n"
|
737 |
"which will change its syntax from dark -vf mp to light -vf.\n"
|
738 |
"Thou shalst not make spells or scripts that depend on it\n");
|
739 |
|
740 |
m->avfctx= ctx; |
741 |
|
742 |
if(!args || 1!=sscanf(args, "%255[^:]", name)){ |
743 |
av_log(ctx, AV_LOG_ERROR, "Invalid parameter.\n");
|
744 |
return AVERROR(EINVAL);
|
745 |
} |
746 |
args+= strlen(name)+1;
|
747 |
|
748 |
for(i=0; ;i++){ |
749 |
if(!filters[i] || !strcmp(name, filters[i]->name))
|
750 |
break;
|
751 |
} |
752 |
|
753 |
if(!filters[i]){
|
754 |
av_log(ctx, AV_LOG_ERROR, "Unknown filter %s\n", name);
|
755 |
return AVERROR(EINVAL);
|
756 |
} |
757 |
|
758 |
memset(&m->vf,0,sizeof(m->vf)); |
759 |
m->vf.info= filters[i]; |
760 |
|
761 |
m->vf.next = &m->next_vf; |
762 |
m->vf.put_image = vf_next_put_image; |
763 |
m->vf.config = vf_next_config; |
764 |
m->vf.query_format= vf_default_query_format; |
765 |
m->vf.control = vf_next_control; |
766 |
m->vf.default_caps=VFCAP_ACCEPT_STRIDE; |
767 |
m->vf.default_reqs=0;
|
768 |
if(m->vf.info->opts)
|
769 |
av_log(ctx, AV_LOG_ERROR, "opts / m_struct_set is unsupported\n");
|
770 |
#if 0
|
771 |
if(vf->info->opts) { // vf_vo get some special argument
|
772 |
const m_struct_t* st = vf->info->opts;
|
773 |
void* vf_priv = m_struct_alloc(st);
|
774 |
int n;
|
775 |
for(n = 0 ; args && args[2*n] ; n++)
|
776 |
m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
|
777 |
vf->priv = vf_priv;
|
778 |
args = NULL;
|
779 |
} else // Otherwise we should have the '_oldargs_'
|
780 |
if(args && !strcmp(args[0],"_oldargs_"))
|
781 |
args = (char**)args[1];
|
782 |
else
|
783 |
args = NULL;
|
784 |
#endif
|
785 |
if(m->vf.info->vf_open(&m->vf, args)<=0){ |
786 |
av_log(ctx, AV_LOG_ERROR, "vf_open() of %s with arg=%s failed\n", name, args);
|
787 |
return -1; |
788 |
} |
789 |
|
790 |
return 0; |
791 |
} |
792 |
|
793 |
static int query_formats(AVFilterContext *ctx) |
794 |
{ |
795 |
AVFilterFormats *avfmts=NULL;
|
796 |
MPContext *m = ctx->priv; |
797 |
int i;
|
798 |
|
799 |
for(i=0; conversion_map[i].fmt; i++){ |
800 |
av_log(ctx, AV_LOG_DEBUG, "query: %X\n", conversion_map[i].fmt);
|
801 |
if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
|
802 |
av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
|
803 |
avfilter_add_format(&avfmts, conversion_map[i].pix_fmt); |
804 |
} |
805 |
} |
806 |
|
807 |
//We assume all allowed input formats are also allowed output formats
|
808 |
avfilter_set_common_formats(ctx, avfmts); |
809 |
return 0; |
810 |
} |
811 |
|
812 |
static int config_inprops(AVFilterLink *inlink) |
813 |
{ |
814 |
MPContext *m = inlink->dst->priv; |
815 |
int i;
|
816 |
for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++); |
817 |
|
818 |
av_assert0(conversion_map[i].fmt && inlink->w && inlink->h); |
819 |
|
820 |
m->vf.fmt.have_configured = 1;
|
821 |
m->vf.fmt.orig_height = inlink->h; |
822 |
m->vf.fmt.orig_width = inlink->w; |
823 |
m->vf.fmt.orig_fmt = conversion_map[i].fmt; |
824 |
|
825 |
if(m->vf.config(&m->vf, inlink->w, inlink->h, inlink->w, inlink->h, 0, conversion_map[i].fmt)<=0) |
826 |
return -1; |
827 |
|
828 |
return 0; |
829 |
} |
830 |
|
831 |
static int config_outprops(AVFilterLink *outlink) |
832 |
{ |
833 |
MPContext *m = outlink->src->priv; |
834 |
|
835 |
outlink->w = m->next_vf.w; |
836 |
outlink->h = m->next_vf.h; |
837 |
|
838 |
return 0; |
839 |
} |
840 |
|
841 |
static int request_frame(AVFilterLink *outlink) |
842 |
{ |
843 |
MPContext *m = outlink->src->priv; |
844 |
int ret;
|
845 |
|
846 |
av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
|
847 |
|
848 |
for(m->frame_returned=0; !m->frame_returned;){ |
849 |
ret=avfilter_request_frame(outlink->src->inputs[0]);
|
850 |
if(ret<0) |
851 |
break;
|
852 |
} |
853 |
|
854 |
av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame ret=%d\n", ret);
|
855 |
return ret;
|
856 |
} |
857 |
|
858 |
static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) |
859 |
{ |
860 |
} |
861 |
|
862 |
static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) |
863 |
{ |
864 |
} |
865 |
|
866 |
static void end_frame(AVFilterLink *inlink) |
867 |
{ |
868 |
MPContext *m = inlink->dst->priv; |
869 |
AVFilterBufferRef *inpic = inlink->cur_buf; |
870 |
AVFilterLink *outlink = inlink->dst->outputs[0];
|
871 |
int i;
|
872 |
double pts= MP_NOPTS_VALUE;
|
873 |
mp_image_t* mpi = new_mp_image(inpic->video->w, inpic->video->h); |
874 |
|
875 |
if(inpic->pts != AV_NOPTS_VALUE)
|
876 |
pts= inpic->pts / av_q2d(inlink->time_base); |
877 |
|
878 |
for(i=0; conversion_map[i].fmt && conversion_map[i].pix_fmt != inlink->format; i++); |
879 |
mp_image_setfmt(mpi,conversion_map[i].fmt); |
880 |
|
881 |
memcpy(mpi->planes, inpic->data, FFMIN(sizeof(inpic->data) , sizeof(mpi->planes))); |
882 |
memcpy(mpi->stride, inpic->linesize, FFMIN(sizeof(inpic->linesize), sizeof(mpi->stride))); |
883 |
|
884 |
//FIXME pass interleced & tff flags around
|
885 |
|
886 |
// mpi->flags|=MP_IMGFLAG_ALLOCATED; ?
|
887 |
mpi->flags |= MP_IMGFLAG_READABLE; |
888 |
if(!(inpic->perms & AV_PERM_WRITE))
|
889 |
mpi->flags |= MP_IMGFLAG_PRESERVE; |
890 |
if(m->vf.put_image(&m->vf, mpi, pts) == 0){ |
891 |
av_log(m->avfctx, AV_LOG_DEBUG, "put_image() says skip\n");
|
892 |
} |
893 |
free_mp_image(mpi); |
894 |
|
895 |
// avfilter_unref_buffer(inpic);
|
896 |
} |
897 |
|
898 |
AVFilter avfilter_vf_mp = { |
899 |
.name = "mp",
|
900 |
.description = NULL_IF_CONFIG_SMALL("libmpcodecs wrapper."),
|
901 |
.init = init, |
902 |
.priv_size = sizeof(MPContext),
|
903 |
.query_formats = query_formats, |
904 |
|
905 |
.inputs = (AVFilterPad[]) {{ .name = "default",
|
906 |
.type = AVMEDIA_TYPE_VIDEO, |
907 |
.start_frame = start_frame, |
908 |
.draw_slice = null_draw_slice, |
909 |
.end_frame = end_frame, |
910 |
.config_props = config_inprops, |
911 |
.min_perms = AV_PERM_READ, }, |
912 |
{ .name = NULL}},
|
913 |
.outputs = (AVFilterPad[]) {{ .name = "default",
|
914 |
.type = AVMEDIA_TYPE_VIDEO, |
915 |
.request_frame = request_frame, |
916 |
.config_props = config_outprops, }, |
917 |
{ .name = NULL}},
|
918 |
}; |