~ubuntu-branches/ubuntu/quantal/mplayer2/quantal-proposed

« back to all changes in this revision

Viewing changes to libmpcodecs/vf.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2012-01-12 22:59:30 UTC
  • mfrom: (5.1.8 sid)
  • Revision ID: package-import@ubuntu.com-20120112225930-jsg10o7na7nk73w5
Tags: 2.0-426-gc32b3ed-2
* Upload to unstable
* don't build-depend on libcdparanoia-dev on the hurd

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include <stdio.h>
20
20
#include <stdlib.h>
21
21
#include <string.h>
 
22
#include <assert.h>
22
23
 
23
24
#include "config.h"
24
25
#if HAVE_MALLOC_H
25
26
#include <malloc.h>
26
27
#endif
27
28
 
28
 
#ifdef MP_DEBUG
29
 
#include <assert.h>
30
 
#endif
31
 
 
32
29
#include "mp_msg.h"
33
30
#include "m_option.h"
34
31
#include "m_struct.h"
119
116
extern const vf_info_t vf_info_stereo3d;
120
117
 
121
118
// list of available filters:
122
 
static const vf_info_t* const filter_list[]={
 
119
static const vf_info_t *const filter_list[] = {
123
120
    &vf_info_rectangle,
124
121
#ifdef HAVE_POSIX_SELECT
125
122
    &vf_info_bmovl,
136
133
    &vf_info_mirror,
137
134
    &vf_info_palette,
138
135
    &vf_info_pp7,
139
 
#ifdef CONFIG_FFMPEG
 
136
 
140
137
    &vf_info_pp,
141
138
    &vf_info_lavc,
142
139
    &vf_info_lavcdeint,
143
140
    &vf_info_screenshot,
 
141
    &vf_info_fspp,
144
142
    &vf_info_uspp,
145
 
#endif
 
143
 
146
144
    &vf_info_dvbscale,
147
145
    &vf_info_cropdetect,
148
146
    &vf_info_test,
185
183
    &vf_info_hue,
186
184
#ifdef CONFIG_FFMPEG_INTERNALS
187
185
    &vf_info_spp,
188
 
    &vf_info_fspp,
189
 
    &vf_info_qp,
190
186
    &vf_info_mcdeint,
191
187
#endif
192
 
#ifdef CONFIG_FFMPEG_EVAL_API
193
188
    &vf_info_geq,
194
 
#endif
 
189
    &vf_info_qp,
195
190
    &vf_info_yuvcsp,
196
191
    &vf_info_kerndeint,
197
192
    &vf_info_rgbtest,
212
207
 
213
208
// For the vf option
214
209
const m_obj_list_t vf_obj_list = {
215
 
  (void**)filter_list,
216
 
  M_ST_OFF(vf_info_t,name),
217
 
  M_ST_OFF(vf_info_t,info),
218
 
  M_ST_OFF(vf_info_t,opts)
 
210
    (void **)filter_list,
 
211
    M_ST_OFF(vf_info_t, name),
 
212
    M_ST_OFF(vf_info_t, info),
 
213
    M_ST_OFF(vf_info_t, opts)
219
214
};
220
215
 
221
216
//============================================================================
222
217
// mpi stuff:
223
218
 
224
 
void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h){
 
219
void vf_mpi_clear(mp_image_t *mpi, int x0, int y0, int w, int h)
 
220
{
225
221
    int y;
226
 
    if(mpi->flags&MP_IMGFLAG_PLANAR){
227
 
        y0&=~1;h+=h&1;
228
 
        if(x0==0 && w==mpi->width){
229
 
            // full width clear:
230
 
            memset(mpi->planes[0]+mpi->stride[0]*y0,0,mpi->stride[0]*h);
231
 
            memset(mpi->planes[1]+mpi->stride[1]*(y0>>mpi->chroma_y_shift),128,mpi->stride[1]*(h>>mpi->chroma_y_shift));
232
 
            memset(mpi->planes[2]+mpi->stride[2]*(y0>>mpi->chroma_y_shift),128,mpi->stride[2]*(h>>mpi->chroma_y_shift));
233
 
        } else
234
 
        for(y=y0;y<y0+h;y+=2){
235
 
            memset(mpi->planes[0]+x0+mpi->stride[0]*y,0,w);
236
 
            memset(mpi->planes[0]+x0+mpi->stride[0]*(y+1),0,w);
237
 
            memset(mpi->planes[1]+(x0>>mpi->chroma_x_shift)+mpi->stride[1]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
238
 
            memset(mpi->planes[2]+(x0>>mpi->chroma_x_shift)+mpi->stride[2]*(y>>mpi->chroma_y_shift),128,(w>>mpi->chroma_x_shift));
239
 
        }
240
 
        return;
 
222
    if (mpi->flags & MP_IMGFLAG_PLANAR) {
 
223
        y0 &= ~1;
 
224
        h += h & 1;
 
225
        if (x0 == 0 && w == mpi->width) {
 
226
            // full width clear:
 
227
            memset(mpi->planes[0] + mpi->stride[0] * y0, 0, mpi->stride[0] * h);
 
228
            memset(mpi->planes[1] + mpi->stride[1] *(y0 >> mpi->chroma_y_shift),
 
229
                   128, mpi->stride[1] * (h >> mpi->chroma_y_shift));
 
230
            memset(mpi->planes[2] + mpi->stride[2] *(y0 >> mpi->chroma_y_shift),
 
231
                   128, mpi->stride[2] * (h >> mpi->chroma_y_shift));
 
232
        } else
 
233
            for (y = y0; y < y0 + h; y += 2) {
 
234
                memset(mpi->planes[0] + x0 + mpi->stride[0] * y, 0, w);
 
235
                memset(mpi->planes[0] + x0 + mpi->stride[0] * (y + 1), 0, w);
 
236
                memset(mpi->planes[1] + (x0 >> mpi->chroma_x_shift) +
 
237
                       mpi->stride[1] * (y >> mpi->chroma_y_shift),
 
238
                       128, (w >> mpi->chroma_x_shift));
 
239
                memset(mpi->planes[2] + (x0 >> mpi->chroma_x_shift) +
 
240
                       mpi->stride[2] * (y >> mpi->chroma_y_shift),
 
241
                       128, (w >> mpi->chroma_x_shift));
 
242
            }
 
243
        return;
241
244
    }
242
245
    // packed:
243
 
    for(y=y0;y<y0+h;y++){
244
 
        unsigned char* dst=mpi->planes[0]+mpi->stride[0]*y+(mpi->bpp>>3)*x0;
245
 
        if(mpi->flags&MP_IMGFLAG_YUV){
246
 
            unsigned int* p=(unsigned int*) dst;
247
 
            int size=(mpi->bpp>>3)*w/4;
248
 
            int i;
 
246
    for (y = y0; y < y0 + h; y++) {
 
247
        unsigned char *dst = mpi->planes[0] + mpi->stride[0] * y +
 
248
                             (mpi->bpp >> 3) * x0;
 
249
        if (mpi->flags & MP_IMGFLAG_YUV) {
 
250
            unsigned int *p = (unsigned int *) dst;
 
251
            int size = (mpi->bpp >> 3) * w / 4;
 
252
            int i;
249
253
#if HAVE_BIGENDIAN
250
254
#define CLEAR_PACKEDYUV_PATTERN 0x00800080
251
255
#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x80008000
253
257
#define CLEAR_PACKEDYUV_PATTERN 0x80008000
254
258
#define CLEAR_PACKEDYUV_PATTERN_SWAPPED 0x00800080
255
259
#endif
256
 
            if(mpi->flags&MP_IMGFLAG_SWAPPED){
257
 
                for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
258
 
                for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN_SWAPPED;
259
 
            } else {
260
 
                for(i=0;i<size-3;i+=4) p[i]=p[i+1]=p[i+2]=p[i+3]=CLEAR_PACKEDYUV_PATTERN;
261
 
                for(;i<size;i++) p[i]=CLEAR_PACKEDYUV_PATTERN;
262
 
            }
263
 
        } else
264
 
            memset(dst,0,(mpi->bpp>>3)*w);
 
260
            if (mpi->flags & MP_IMGFLAG_SWAPPED) {
 
261
                for (i = 0; i < size - 3; i += 4)
 
262
                    p[i] = p[i + 1] = p[i + 2] = p[i + 3] = CLEAR_PACKEDYUV_PATTERN_SWAPPED;
 
263
                for (; i < size; i++)
 
264
                    p[i] = CLEAR_PACKEDYUV_PATTERN_SWAPPED;
 
265
            } else {
 
266
                for (i = 0; i < size - 3; i += 4)
 
267
                    p[i] = p[i + 1] = p[i + 2] = p[i + 3] = CLEAR_PACKEDYUV_PATTERN;
 
268
                for (; i < size; i++)
 
269
                    p[i] = CLEAR_PACKEDYUV_PATTERN;
 
270
            }
 
271
        } else
 
272
            memset(dst, 0, (mpi->bpp >> 3) * w);
265
273
    }
266
274
}
267
275
 
268
 
mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h){
269
 
  mp_image_t* mpi=NULL;
270
 
  int w2;
271
 
  int number = mp_imgtype >> 16;
272
 
 
273
 
#ifdef MP_DEBUG
274
 
  assert(w == -1 || w >= vf->w);
275
 
  assert(h == -1 || h >= vf->h);
276
 
  assert(vf->w > 0);
277
 
  assert(vf->h > 0);
278
 
#endif
279
 
 
280
 
//  fprintf(stderr, "get_image: %d:%d, vf: %d:%d\n", w,h,vf->w,vf->h);
281
 
 
282
 
  if (w == -1) w = vf->w;
283
 
  if (h == -1) h = vf->h;
284
 
 
285
 
  w2=(mp_imgflag&MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE)?((w+15)&(~15)):w;
286
 
 
287
 
  if(vf->put_image==vf_next_put_image){
288
 
      // passthru mode, if the filter uses the fallback/default put_image() code
289
 
      return vf_get_image(vf->next,outfmt,mp_imgtype,mp_imgflag,w,h);
290
 
  }
291
 
 
292
 
  // Note: we should call libvo first to check if it supports direct rendering
293
 
  // and if not, then fallback to software buffers:
294
 
  switch(mp_imgtype & 0xff){
295
 
  case MP_IMGTYPE_EXPORT:
296
 
    if(!vf->imgctx.export_images[0]) vf->imgctx.export_images[0]=new_mp_image(w2,h);
297
 
    mpi=vf->imgctx.export_images[0];
298
 
    break;
299
 
  case MP_IMGTYPE_STATIC:
300
 
    if(!vf->imgctx.static_images[0]) vf->imgctx.static_images[0]=new_mp_image(w2,h);
301
 
    mpi=vf->imgctx.static_images[0];
302
 
    break;
303
 
  case MP_IMGTYPE_TEMP:
304
 
    if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
305
 
    mpi=vf->imgctx.temp_images[0];
306
 
    break;
307
 
  case MP_IMGTYPE_IPB:
308
 
    if(!(mp_imgflag&MP_IMGFLAG_READABLE)){ // B frame:
309
 
      if(!vf->imgctx.temp_images[0]) vf->imgctx.temp_images[0]=new_mp_image(w2,h);
310
 
      mpi=vf->imgctx.temp_images[0];
311
 
      break;
312
 
    }
313
 
  case MP_IMGTYPE_IP:
314
 
    if(!vf->imgctx.static_images[vf->imgctx.static_idx]) vf->imgctx.static_images[vf->imgctx.static_idx]=new_mp_image(w2,h);
315
 
    mpi=vf->imgctx.static_images[vf->imgctx.static_idx];
316
 
    vf->imgctx.static_idx^=1;
317
 
    break;
318
 
  case MP_IMGTYPE_NUMBERED:
319
 
    if (number == -1) {
320
 
      int i;
321
 
      for (i = 0; i < NUM_NUMBERED_MPI; i++)
322
 
        if (!vf->imgctx.numbered_images[i] || !vf->imgctx.numbered_images[i]->usage_count)
323
 
          break;
324
 
      number = i;
325
 
    }
326
 
    if (number < 0 || number >= NUM_NUMBERED_MPI) return NULL;
327
 
    if (!vf->imgctx.numbered_images[number]) vf->imgctx.numbered_images[number] = new_mp_image(w2,h);
328
 
    mpi = vf->imgctx.numbered_images[number];
329
 
    mpi->number = number;
330
 
    break;
331
 
  }
332
 
  if(mpi){
333
 
    mpi->type=mp_imgtype;
334
 
    mpi->w=vf->w; mpi->h=vf->h;
335
 
    // keep buffer allocation status & color flags only:
336
 
//    mpi->flags&=~(MP_IMGFLAG_PRESERVE|MP_IMGFLAG_READABLE|MP_IMGFLAG_DIRECT);
337
 
    mpi->flags&=MP_IMGFLAG_ALLOCATED|MP_IMGFLAG_TYPE_DISPLAYED|MP_IMGFLAGMASK_COLORS;
338
 
    // accept restrictions, draw_slice and palette flags only:
339
 
    mpi->flags|=mp_imgflag&(MP_IMGFLAGMASK_RESTRICTIONS|MP_IMGFLAG_DRAW_CALLBACK|MP_IMGFLAG_RGB_PALETTE);
340
 
    if(!vf->draw_slice) mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
341
 
    if(mpi->width!=w2 || mpi->height!=h){
342
 
//      printf("vf.c: MPI parameters changed!  %dx%d -> %dx%d   \n", mpi->width,mpi->height,w2,h);
343
 
        if(mpi->flags&MP_IMGFLAG_ALLOCATED){
344
 
            if(mpi->width<w2 || mpi->height<h){
345
 
                // need to re-allocate buffer memory:
346
 
                av_free(mpi->planes[0]);
347
 
                mpi->flags&=~MP_IMGFLAG_ALLOCATED;
348
 
                mp_msg(MSGT_VFILTER,MSGL_V,"vf.c: have to REALLOCATE buffer memory :(\n");
349
 
            }
350
 
//      } else {
351
 
        } {
352
 
            mpi->width=w2; mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
353
 
            mpi->height=h; mpi->chroma_height=(h + (1<<mpi->chroma_y_shift) - 1)>>mpi->chroma_y_shift;
354
 
        }
355
 
    }
356
 
    if(!mpi->bpp) mp_image_setfmt(mpi,outfmt);
357
 
    if(!(mpi->flags&MP_IMGFLAG_ALLOCATED) && mpi->type>MP_IMGTYPE_EXPORT){
358
 
 
359
 
        // check libvo first!
360
 
        if(vf->get_image) vf->get_image(vf,mpi);
361
 
 
362
 
        if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
363
 
          // non-direct and not yet allocated image. allocate it!
364
 
          if (!mpi->bpp) { // no way we can allocate this
365
 
              mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
366
 
                     "vf_get_image: Tried to allocate a format that can not be allocated!\n");
367
 
              return NULL;
368
 
          }
369
 
 
370
 
          // check if codec prefer aligned stride:
371
 
          if(mp_imgflag&MP_IMGFLAG_PREFER_ALIGNED_STRIDE){
372
 
              int align=(mpi->flags&MP_IMGFLAG_PLANAR &&
373
 
                         mpi->flags&MP_IMGFLAG_YUV) ?
374
 
                         (8<<mpi->chroma_x_shift)-1 : 15; // -- maybe FIXME
375
 
              w2=((w+align)&(~align));
376
 
              if(mpi->width!=w2){
377
 
                  // we have to change width... check if we CAN co it:
378
 
                  int flags=vf->query_format(vf,outfmt); // should not fail
379
 
                  if(!(flags&3)) mp_msg(MSGT_DECVIDEO,MSGL_WARN,"??? vf_get_image{vf->query_format(outfmt)} failed!\n");
380
 
//                printf("query -> 0x%X    \n",flags);
381
 
                  if(flags&VFCAP_ACCEPT_STRIDE){
382
 
                      mpi->width=w2;
383
 
                      mpi->chroma_width=(w2 + (1<<mpi->chroma_x_shift) - 1)>>mpi->chroma_x_shift;
384
 
                  }
385
 
              }
386
 
          }
387
 
 
388
 
          mp_image_alloc_planes(mpi);
389
 
//        printf("clearing img!\n");
390
 
          vf_mpi_clear(mpi,0,0,mpi->width,mpi->height);
391
 
        }
392
 
    }
393
 
    if(mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)
394
 
        if(vf->start_slice) vf->start_slice(vf,mpi);
395
 
    if(!(mpi->flags&MP_IMGFLAG_TYPE_DISPLAYED)){
396
 
            mp_msg(MSGT_DECVIDEO,MSGL_V,"*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
397
 
                  vf->info->name,
398
 
                  (mpi->type==MP_IMGTYPE_EXPORT)?"Exporting":
399
 
                  ((mpi->flags&MP_IMGFLAG_DIRECT)?"Direct Rendering":"Allocating"),
400
 
                  (mpi->flags&MP_IMGFLAG_DRAW_CALLBACK)?" (slices)":"",
401
 
                  mpi->width,mpi->height,mpi->bpp,
402
 
                  (mpi->flags&MP_IMGFLAG_YUV)?"YUV":((mpi->flags&MP_IMGFLAG_SWAPPED)?"BGR":"RGB"),
403
 
                  (mpi->flags&MP_IMGFLAG_PLANAR)?"planar":"packed",
404
 
                  mpi->bpp*mpi->width*mpi->height/8);
405
 
            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",
406
 
                mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
407
 
                mpi->stride[0], mpi->stride[1], mpi->stride[2],
408
 
                mpi->chroma_width, mpi->chroma_height, mpi->chroma_x_shift, mpi->chroma_y_shift);
409
 
            mpi->flags|=MP_IMGFLAG_TYPE_DISPLAYED;
410
 
    }
411
 
 
412
 
  mpi->qscale = NULL;
413
 
  }
414
 
  mpi->usage_count++;
415
 
//    printf("\rVF_MPI: %p %p %p %d %d %d    \n",
416
 
//      mpi->planes[0],mpi->planes[1],mpi->planes[2],
417
 
//      mpi->stride[0],mpi->stride[1],mpi->stride[2]);
418
 
  return mpi;
 
276
mp_image_t *vf_get_image(vf_instance_t *vf, unsigned int outfmt,
 
277
                         int mp_imgtype, int mp_imgflag, int w, int h)
 
278
{
 
279
    mp_image_t *mpi = NULL;
 
280
    int w2;
 
281
    int number = mp_imgtype >> 16;
 
282
 
 
283
    assert(w == -1 || w >= vf->w);
 
284
    assert(h == -1 || h >= vf->h);
 
285
    assert(vf->w > 0);
 
286
    assert(vf->h > 0);
 
287
 
 
288
    if (w == -1)
 
289
        w = vf->w;
 
290
    if (h == -1)
 
291
        h = vf->h;
 
292
 
 
293
    w2 = (mp_imgflag & MP_IMGFLAG_ACCEPT_ALIGNED_STRIDE) ?
 
294
            ((w + 15) & (~15)) : w;
 
295
 
 
296
    if (vf->put_image == vf_next_put_image) {
 
297
        // passthru mode, if the filter uses the fallback/default put_image()
 
298
        return vf_get_image(vf->next, outfmt, mp_imgtype, mp_imgflag, w, h);
 
299
    }
 
300
 
 
301
    // Note: we should call libvo first to check if it supports direct rendering
 
302
    // and if not, then fallback to software buffers:
 
303
    switch (mp_imgtype & 0xff) {
 
304
    case MP_IMGTYPE_EXPORT:
 
305
        if (!vf->imgctx.export_images[0])
 
306
            vf->imgctx.export_images[0] = new_mp_image(w2, h);
 
307
        mpi = vf->imgctx.export_images[0];
 
308
        break;
 
309
    case MP_IMGTYPE_STATIC:
 
310
        if (!vf->imgctx.static_images[0])
 
311
            vf->imgctx.static_images[0] = new_mp_image(w2, h);
 
312
        mpi = vf->imgctx.static_images[0];
 
313
        break;
 
314
    case MP_IMGTYPE_TEMP:
 
315
        if (!vf->imgctx.temp_images[0])
 
316
            vf->imgctx.temp_images[0] = new_mp_image(w2, h);
 
317
        mpi = vf->imgctx.temp_images[0];
 
318
        break;
 
319
    case MP_IMGTYPE_IPB:
 
320
        if (!(mp_imgflag & MP_IMGFLAG_READABLE)) { // B frame:
 
321
            if (!vf->imgctx.temp_images[0])
 
322
                vf->imgctx.temp_images[0] = new_mp_image(w2, h);
 
323
            mpi = vf->imgctx.temp_images[0];
 
324
            break;
 
325
        }
 
326
    case MP_IMGTYPE_IP:
 
327
        if (!vf->imgctx.static_images[vf->imgctx.static_idx])
 
328
            vf->imgctx.static_images[vf->imgctx.static_idx] = new_mp_image(w2, h);
 
329
        mpi = vf->imgctx.static_images[vf->imgctx.static_idx];
 
330
        vf->imgctx.static_idx ^= 1;
 
331
        break;
 
332
    case MP_IMGTYPE_NUMBERED:
 
333
        if (number == -1) {
 
334
            int i;
 
335
            for (i = 0; i < NUM_NUMBERED_MPI; i++)
 
336
                if (!vf->imgctx.numbered_images[i] ||
 
337
                        !vf->imgctx.numbered_images[i]->usage_count)
 
338
                    break;
 
339
            number = i;
 
340
        }
 
341
        if (number < 0 || number >= NUM_NUMBERED_MPI)
 
342
            return NULL;
 
343
        if (!vf->imgctx.numbered_images[number])
 
344
            vf->imgctx.numbered_images[number] = new_mp_image(w2, h);
 
345
        mpi = vf->imgctx.numbered_images[number];
 
346
        mpi->number = number;
 
347
        break;
 
348
    }
 
349
    if (mpi) {
 
350
        mpi->type = mp_imgtype;
 
351
        mpi->w = vf->w;
 
352
        mpi->h = vf->h;
 
353
        // keep buffer allocation status & color flags only:
 
354
        mpi->flags &= MP_IMGFLAG_ALLOCATED | MP_IMGFLAG_TYPE_DISPLAYED |
 
355
                      MP_IMGFLAGMASK_COLORS;
 
356
        // accept restrictions, draw_slice and palette flags only:
 
357
        mpi->flags |= mp_imgflag & (MP_IMGFLAGMASK_RESTRICTIONS |
 
358
                          MP_IMGFLAG_DRAW_CALLBACK | MP_IMGFLAG_RGB_PALETTE);
 
359
        if (!vf->draw_slice)
 
360
            mpi->flags &= ~MP_IMGFLAG_DRAW_CALLBACK;
 
361
        if (mpi->width != w2 || mpi->height != h) {
 
362
            if (mpi->flags & MP_IMGFLAG_ALLOCATED) {
 
363
                if (mpi->width < w2 || mpi->height < h) {
 
364
                    // need to re-allocate buffer memory:
 
365
                    av_free(mpi->planes[0]);
 
366
                    mpi->flags &= ~MP_IMGFLAG_ALLOCATED;
 
367
                    mp_msg(MSGT_VFILTER, MSGL_V,
 
368
                           "vf.c: have to REALLOCATE buffer memory :(\n");
 
369
                }
 
370
            }
 
371
            mpi->width = w2;
 
372
            mpi->chroma_width = (w2 + (1 << mpi->chroma_x_shift) - 1) >>
 
373
                                                     mpi->chroma_x_shift;
 
374
            mpi->height = h;
 
375
            mpi->chroma_height = (h + (1 << mpi->chroma_y_shift) - 1) >>
 
376
                                                     mpi->chroma_y_shift;
 
377
        }
 
378
        if (!mpi->bpp)
 
379
            mp_image_setfmt(mpi, outfmt);
 
380
        if (!(mpi->flags & MP_IMGFLAG_ALLOCATED) &&
 
381
                mpi->type > MP_IMGTYPE_EXPORT) {
 
382
            // check libvo first!
 
383
            if (vf->get_image)
 
384
                vf->get_image(vf, mpi);
 
385
 
 
386
            if (!(mpi->flags & MP_IMGFLAG_DIRECT)) {
 
387
                // non-direct and not yet allocated image. allocate it!
 
388
                if (!mpi->bpp) { // no way we can allocate this
 
389
                    mp_msg(MSGT_DECVIDEO, MSGL_FATAL,
 
390
                           "vf_get_image: Tried to allocate a format that "
 
391
                           "can not be allocated!\n");
 
392
                    return NULL;
 
393
                }
 
394
 
 
395
                // check if codec prefer aligned stride:
 
396
                if (mp_imgflag & MP_IMGFLAG_PREFER_ALIGNED_STRIDE) {
 
397
                    int align = (mpi->flags & MP_IMGFLAG_PLANAR &&
 
398
                                 mpi->flags & MP_IMGFLAG_YUV) ?
 
399
                                (8 << mpi->chroma_x_shift) - 1 : 15; // OK?
 
400
                    w2 = ((w + align) & (~align));
 
401
                    if (mpi->width != w2) {
 
402
                        // we have to change width... check if we CAN co it:
 
403
                        int flags = vf->query_format(vf, outfmt);
 
404
                        // should not fail
 
405
                        if (!(flags & (VFCAP_CSP_SUPPORTED |
 
406
                                       VFCAP_CSP_SUPPORTED_BY_HW)))
 
407
                            mp_msg(MSGT_DECVIDEO, MSGL_WARN,
 
408
                                   "??? vf_get_image{vf->query_format(outfmt)} "
 
409
                                   "failed!\n");
 
410
                        if (flags & VFCAP_ACCEPT_STRIDE) {
 
411
                            mpi->width = w2;
 
412
                            mpi->chroma_width =
 
413
                                (w2 + (1 << mpi->chroma_x_shift) - 1) >>
 
414
                                mpi->chroma_x_shift;
 
415
                        }
 
416
                    }
 
417
                }
 
418
 
 
419
                mp_image_alloc_planes(mpi);
 
420
                vf_mpi_clear(mpi, 0, 0, mpi->width, mpi->height);
 
421
            }
 
422
        }
 
423
        if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
 
424
            if (vf->start_slice)
 
425
                vf->start_slice(vf, mpi);
 
426
        if (!(mpi->flags & MP_IMGFLAG_TYPE_DISPLAYED)) {
 
427
            mp_msg(MSGT_DECVIDEO, MSGL_V,
 
428
                   "*** [%s] %s%s mp_image_t, %dx%dx%dbpp %s %s, %d bytes\n",
 
429
                   vf->info->name,
 
430
                   (mpi->type == MP_IMGTYPE_EXPORT) ? "Exporting" :
 
431
                   ((mpi->flags & MP_IMGFLAG_DIRECT) ?
 
432
                            "Direct Rendering" : "Allocating"),
 
433
                   (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) ? " (slices)" : "",
 
434
                   mpi->width, mpi->height, mpi->bpp,
 
435
                   (mpi->flags & MP_IMGFLAG_YUV) ? "YUV" :
 
436
                           ((mpi->flags & MP_IMGFLAG_SWAPPED) ? "BGR" : "RGB"),
 
437
                   (mpi->flags & MP_IMGFLAG_PLANAR) ? "planar" : "packed",
 
438
                   mpi->bpp * mpi->width * mpi->height / 8);
 
439
            mp_msg(MSGT_DECVIDEO, MSGL_DBG2, "(imgfmt: %x, planes: %p,%p,%p "
 
440
                   "strides: %d,%d,%d, chroma: %dx%d, shift: h:%d,v:%d)\n",
 
441
                   mpi->imgfmt, mpi->planes[0], mpi->planes[1], mpi->planes[2],
 
442
                   mpi->stride[0], mpi->stride[1], mpi->stride[2],
 
443
                   mpi->chroma_width, mpi->chroma_height,
 
444
                   mpi->chroma_x_shift, mpi->chroma_y_shift);
 
445
            mpi->flags |= MP_IMGFLAG_TYPE_DISPLAYED;
 
446
        }
 
447
        mpi->qscale = NULL;
 
448
    }
 
449
    mpi->usage_count++;
 
450
    return mpi;
419
451
}
420
452
 
421
453
//============================================================================
422
454
 
423
455
// By default vf doesn't accept MPEGPES
424
 
static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt){
425
 
  if(fmt == IMGFMT_MPEGPES) return 0;
426
 
  return vf_next_query_format(vf,fmt);
 
456
static int vf_default_query_format(struct vf_instance *vf, unsigned int fmt)
 
457
{
 
458
    if (fmt == IMGFMT_MPEGPES)
 
459
        return 0;
 
460
    return vf_next_query_format(vf, fmt);
427
461
}
428
462
 
429
463
struct vf_instance *vf_open_plugin_noerr(struct MPOpts *opts,
430
 
                                         const vf_info_t * const *filter_list,
 
464
                                         const vf_info_t *const *filter_list,
431
465
                                         vf_instance_t *next, const char *name,
432
466
                                         char **args, int *retcode)
433
467
{
434
 
    vf_instance_t* vf;
 
468
    vf_instance_t *vf;
435
469
    int i;
436
 
    for(i=0;;i++){
437
 
        if(!filter_list[i]){
438
 
            mp_tmsg(MSGT_VFILTER,MSGL_ERR,"Couldn't find video filter '%s'.\n",name);
439
 
            return NULL; // no such filter!
440
 
        }
441
 
        if(!strcmp(filter_list[i]->name,name)) break;
 
470
    for (i = 0;; i++) {
 
471
        if (!filter_list[i]) {
 
472
            mp_tmsg(MSGT_VFILTER, MSGL_ERR,
 
473
                    "Couldn't find video filter '%s'.\n", name);
 
474
            return NULL; // no such filter!
 
475
        }
 
476
        if (!strcmp(filter_list[i]->name, name))
 
477
            break;
442
478
    }
443
479
    vf = calloc(1, sizeof *vf);
444
480
    vf->opts = opts;
445
 
    vf->info=filter_list[i];
446
 
    vf->next=next;
447
 
    vf->config=vf_next_config;
448
 
    vf->control=vf_next_control;
449
 
    vf->query_format=vf_default_query_format;
450
 
    vf->put_image=vf_next_put_image;
451
 
    vf->default_caps=VFCAP_ACCEPT_STRIDE;
452
 
    vf->default_reqs=0;
453
 
    if(vf->info->opts) { // vf_vo get some special argument
454
 
      const m_struct_t* st = vf->info->opts;
455
 
      void* vf_priv = m_struct_alloc(st);
456
 
      int n;
457
 
      for(n = 0 ; args && args[2*n] ; n++)
458
 
        m_struct_set(st,vf_priv,args[2*n],args[2*n+1]);
459
 
      vf->priv = vf_priv;
460
 
      args = NULL;
 
481
    vf->info = filter_list[i];
 
482
    vf->next = next;
 
483
    vf->config = vf_next_config;
 
484
    vf->control = vf_next_control;
 
485
    vf->query_format = vf_default_query_format;
 
486
    vf->put_image = vf_next_put_image;
 
487
    vf->default_caps = VFCAP_ACCEPT_STRIDE;
 
488
    vf->default_reqs = 0;
 
489
    if (vf->info->opts) { // vf_vo get some special argument
 
490
        const m_struct_t *st = vf->info->opts;
 
491
        void *vf_priv = m_struct_alloc(st);
 
492
        int n;
 
493
        for (n = 0; args && args[2 * n]; n++)
 
494
            m_struct_set(st, vf_priv, args[2 * n], bstr(args[2 * n + 1]));
 
495
        vf->priv = vf_priv;
 
496
        args = NULL;
461
497
    } else // Otherwise we should have the '_oldargs_'
462
 
      if(args && !strcmp(args[0],"_oldargs_"))
463
 
        args = (char**)args[1];
464
 
      else
465
 
        args = NULL;
466
 
    *retcode = vf->info->vf_open(vf,(char*)args);
 
498
    if (args && !strcmp(args[0], "_oldargs_"))
 
499
        args = (char **)args[1];
 
500
    else
 
501
        args = NULL;
 
502
    *retcode = vf->info->vf_open(vf, (char *)args);
467
503
    if (*retcode > 0)
468
504
        return vf;
469
505
    free(vf);
471
507
}
472
508
 
473
509
struct vf_instance *vf_open_plugin(struct MPOpts *opts,
474
 
                                   const vf_info_t * const *filter_list,
 
510
                                   const vf_info_t *const *filter_list,
475
511
                                   vf_instance_t *next, const char *name,
476
512
                                   char **args)
477
513
{
483
519
    return vf;
484
520
}
485
521
 
486
 
vf_instance_t* vf_open_filter(struct MPOpts *opts, vf_instance_t* next, const char *name, char **args){
487
 
  if(args && strcmp(args[0],"_oldargs_")) {
488
 
    int i,l = 0;
489
 
    for(i = 0 ; args && args[2*i] ; i++)
490
 
      l += 1 + strlen(args[2*i]) + 1 + strlen(args[2*i+1]);
491
 
    l += strlen(name);
492
 
    {
493
 
      char str[l+1];
494
 
      char* p = str;
495
 
      p += sprintf(str,"%s",name);
496
 
      for(i = 0 ; args && args[2*i] ; i++)
497
 
        p += sprintf(p," %s=%s",args[2*i],args[2*i+1]);
498
 
      mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s]\n",
499
 
             mp_gtext("Opening video filter: "), str);
 
522
vf_instance_t *vf_open_filter(struct MPOpts *opts, vf_instance_t *next,
 
523
                              const char *name, char **args)
 
524
{
 
525
    if (args && strcmp(args[0], "_oldargs_")) {
 
526
        int i, l = 0;
 
527
        for (i = 0; args && args[2 * i]; i++)
 
528
            l += 1 + strlen(args[2 * i]) + 1 + strlen(args[2 * i + 1]);
 
529
        l += strlen(name);
 
530
        {
 
531
            char str[l + 1];
 
532
            char *p = str;
 
533
            p += sprintf(str, "%s", name);
 
534
            for (i = 0; args && args[2 * i]; i++)
 
535
                p += sprintf(p, " %s=%s", args[2 * i], args[2 * i + 1]);
 
536
            mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s]\n",
 
537
                   mp_gtext("Opening video filter: "), str);
 
538
        }
 
539
    } else if (strcmp(name, "vo")) {
 
540
        if (args && strcmp(args[0], "_oldargs_") == 0)
 
541
            mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s=%s]\n",
 
542
                   mp_gtext("Opening video filter: "), name, args[1]);
 
543
        else
 
544
            mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s]\n",
 
545
                   mp_gtext("Opening video filter: "), name);
500
546
    }
501
 
  } else if(strcmp(name,"vo")) {
502
 
    if(args && strcmp(args[0],"_oldargs_") == 0)
503
 
        mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s=%s]\n",
504
 
               mp_gtext("Opening video filter: "), name, args[1]);
505
 
    else
506
 
        mp_msg(MSGT_VFILTER, MSGL_INFO, "%s[%s]\n",
507
 
               mp_gtext("Opening video filter: "), name);
508
 
  }
509
 
  return vf_open_plugin(opts, filter_list,next,name,args);
 
547
    return vf_open_plugin(opts, filter_list, next, name, args);
510
548
}
511
549
 
512
550
/**
516
554
 * \param args argument list for the filter.
517
555
 * \return pointer to the filter instance that was created.
518
556
 */
519
 
vf_instance_t* vf_add_before_vo(vf_instance_t **vf, char *name, char **args) {
520
 
  struct MPOpts *opts = (*vf)->opts;
521
 
  vf_instance_t *vo, *prev = NULL, *new;
522
 
  // Find the last filter (should be vf_vo)
523
 
  for (vo = *vf; vo->next; vo = vo->next)
524
 
    prev = vo;
525
 
  new = vf_open_filter(opts, vo, name, args);
526
 
  if (prev)
527
 
    prev->next = new;
528
 
  else
529
 
    *vf = new;
530
 
  return new;
 
557
vf_instance_t *vf_add_before_vo(vf_instance_t **vf, char *name, char **args)
 
558
{
 
559
    struct MPOpts *opts = (*vf)->opts;
 
560
    vf_instance_t *vo, *prev = NULL, *new;
 
561
    // Find the last filter (should be vf_vo)
 
562
    for (vo = *vf; vo->next; vo = vo->next)
 
563
        prev = vo;
 
564
    new = vf_open_filter(opts, vo, name, args);
 
565
    if (prev)
 
566
        prev->next = new;
 
567
    else
 
568
        *vf = new;
 
569
    return new;
531
570
}
532
571
 
533
572
//============================================================================
534
573
 
535
 
unsigned int vf_match_csp(vf_instance_t** vfp,const unsigned int* list,unsigned int preferred){
536
 
    vf_instance_t* vf=*vfp;
 
574
unsigned int vf_match_csp(vf_instance_t **vfp, const unsigned int *list,
 
575
                          unsigned int preferred)
 
576
{
 
577
    vf_instance_t *vf = *vfp;
537
578
    struct MPOpts *opts = vf->opts;
538
 
    const unsigned int* p;
539
 
    unsigned int best=0;
 
579
    const unsigned int *p;
 
580
    unsigned int best = 0;
540
581
    int ret;
541
 
    if((p=list)) while(*p){
542
 
        ret=vf->query_format(vf,*p);
543
 
        mp_msg(MSGT_VFILTER,MSGL_V,"[%s] query(%s) -> %d\n",vf->info->name,vo_format_name(*p),ret&3);
544
 
        if(ret&2){ best=*p; break;} // no conversion -> bingo!
545
 
        if(ret&1 && !best) best=*p; // best with conversion
546
 
        ++p;
547
 
    }
548
 
    if(best) return best; // bingo, they have common csp!
 
582
    if ((p = list))
 
583
        while (*p) {
 
584
            ret = vf->query_format(vf, *p);
 
585
            mp_msg(MSGT_VFILTER, MSGL_V, "[%s] query(%s) -> %x\n",
 
586
                   vf->info->name, vo_format_name(*p), ret);
 
587
            if (ret & VFCAP_CSP_SUPPORTED_BY_HW) {
 
588
                best = *p;
 
589
                break;
 
590
            }
 
591
            if (ret & VFCAP_CSP_SUPPORTED && !best)
 
592
                best = *p;
 
593
            ++p;
 
594
        }
 
595
    if (best)
 
596
        return best;      // bingo, they have common csp!
549
597
    // ok, then try with scale:
550
 
    if(vf->info == &vf_info_scale) return 0; // avoid infinite recursion!
551
 
    vf=vf_open_filter(opts, vf,"scale",NULL);
552
 
    if(!vf) return 0; // failed to init "scale"
 
598
    if (vf->info == &vf_info_scale)
 
599
        return 0;     // avoid infinite recursion!
 
600
    vf = vf_open_filter(opts, vf, "scale", NULL);
 
601
    if (!vf)
 
602
        return 0;     // failed to init "scale"
553
603
    // try the preferred csp first:
554
 
    if(preferred && vf->query_format(vf,preferred)) best=preferred; else
555
 
    // try the list again, now with "scaler" :
556
 
    if((p=list)) while(*p){
557
 
        ret=vf->query_format(vf,*p);
558
 
        mp_msg(MSGT_VFILTER,MSGL_V,"[%s] query(%s) -> %d\n",vf->info->name,vo_format_name(*p),ret&3);
559
 
        if(ret&2){ best=*p; break;} // no conversion -> bingo!
560
 
        if(ret&1 && !best) best=*p; // best with conversion
561
 
        ++p;
562
 
    }
563
 
    if(best) *vfp=vf; // else uninit vf  !FIXME!
 
604
    if (preferred && vf->query_format(vf, preferred))
 
605
        best = preferred;
 
606
    else
 
607
        // try the list again, now with "scaler" :
 
608
        if ((p = list))
 
609
            while (*p) {
 
610
                ret = vf->query_format(vf, *p);
 
611
                mp_msg(MSGT_VFILTER, MSGL_V, "[%s] query(%s) -> %x\n",
 
612
                       vf->info->name, vo_format_name(*p), ret);
 
613
                if (ret & VFCAP_CSP_SUPPORTED_BY_HW) {
 
614
                    best = *p;
 
615
                    break;
 
616
                }
 
617
                if (ret & VFCAP_CSP_SUPPORTED && !best)
 
618
                    best = *p;
 
619
            ++p;
 
620
        }
 
621
    if (best)
 
622
        *vfp = vf;    // else uninit vf  !FIXME!
564
623
    return best;
565
624
}
566
625
 
567
 
void vf_clone_mpi_attributes(mp_image_t* dst, mp_image_t* src){
568
 
    dst->pict_type= src->pict_type;
 
626
void vf_clone_mpi_attributes(mp_image_t *dst, mp_image_t *src)
 
627
{
 
628
    dst->pict_type = src->pict_type;
569
629
    dst->fields = src->fields;
570
 
    dst->qscale_type= src->qscale_type;
571
 
    if(dst->width == src->width && dst->height == src->height){
572
 
        dst->qstride= src->qstride;
573
 
        dst->qscale= src->qscale;
 
630
    dst->qscale_type = src->qscale_type;
 
631
    if (dst->width == src->width && dst->height == src->height) {
 
632
        dst->qstride = src->qstride;
 
633
        dst->qscale = src->qscale;
574
634
    }
575
635
}
576
636
 
587
647
int vf_output_queued_frame(vf_instance_t *vf)
588
648
{
589
649
    while (1) {
590
 
        int ret;
591
 
        vf_instance_t *current;
592
 
        vf_instance_t *last=NULL;
593
 
        int (*tmp)(vf_instance_t *);
594
 
        for (current = vf; current; current = current->next)
595
 
            if (current->continue_buffered_image)
596
 
                last = current;
597
 
        if (!last)
598
 
            return 0;
599
 
        tmp = last->continue_buffered_image;
600
 
        last->continue_buffered_image = NULL;
601
 
        ret = tmp(last);
602
 
        if (ret)
603
 
            return ret;
 
650
        int ret;
 
651
        vf_instance_t *current;
 
652
        vf_instance_t *last = NULL;
 
653
        int (*tmp)(vf_instance_t *);
 
654
        for (current = vf; current; current = current->next)
 
655
            if (current->continue_buffered_image)
 
656
                last = current;
 
657
        if (!last)
 
658
            return 0;
 
659
        tmp = last->continue_buffered_image;
 
660
        last->continue_buffered_image = NULL;
 
661
        ret = tmp(last);
 
662
        if (ret)
 
663
            return ret;
604
664
    }
605
665
}
606
666
 
616
676
 * In following calls, it verifies that the configuration parameters
617
677
 * are unchanged, and returns either success or error.
618
678
 *
619
 
*/
 
679
 */
620
680
int vf_config_wrapper(struct vf_instance *vf,
621
 
                    int width, int height, int d_width, int d_height,
622
 
                    unsigned int flags, unsigned int outfmt)
 
681
                      int width, int height, int d_width, int d_height,
 
682
                      unsigned int flags, unsigned int outfmt)
623
683
{
624
684
    int r;
625
 
    if ((vf->default_caps&VFCAP_CONSTANT) && vf->fmt.have_configured) {
 
685
    if ((vf->default_caps & VFCAP_CONSTANT) && vf->fmt.have_configured) {
626
686
        if ((vf->fmt.orig_width != width)
627
 
            || (vf->fmt.orig_height != height)
628
 
            || (vf->fmt.orig_fmt != outfmt)) {
629
 
            mp_tmsg(MSGT_VFILTER,MSGL_ERR,"\nNew video file has different resolution or colorspace than the previous one.\n");
 
687
            || (vf->fmt.orig_height != height)
 
688
            || (vf->fmt.orig_fmt != outfmt)) {
 
689
            mp_tmsg(MSGT_VFILTER, MSGL_ERR, "\nNew video file has different "
 
690
                    "resolution or colorspace than the previous one.\n");
630
691
            return 0;
631
692
        }
632
693
        return 1;
636
697
    vf->fmt.orig_width = width;
637
698
    vf->fmt.orig_fmt = outfmt;
638
699
    r = vf->config(vf, width, height, d_width, d_height, flags, outfmt);
639
 
    if (!r) vf->fmt.have_configured = 0;
 
700
    if (!r)
 
701
        vf->fmt.have_configured = 0;
640
702
    return r;
641
703
}
642
704
 
643
705
int vf_next_config(struct vf_instance *vf,
644
 
        int width, int height, int d_width, int d_height,
645
 
        unsigned int voflags, unsigned int outfmt){
 
706
                   int width, int height, int d_width, int d_height,
 
707
                   unsigned int voflags, unsigned int outfmt)
 
708
{
646
709
    struct MPOpts *opts = vf->opts;
647
710
    int miss;
648
 
    int flags=vf->next->query_format(vf->next,outfmt);
649
 
    if(!flags){
650
 
        // hmm. colorspace mismatch!!!
651
 
        // let's insert the 'scale' filter, it does the job for us:
652
 
        vf_instance_t* vf2;
653
 
        if(vf->next->info==&vf_info_scale) return 0; // scale->scale
654
 
        vf2=vf_open_filter(opts, vf->next,"scale",NULL);
655
 
        if(!vf2) return 0; // shouldn't happen!
656
 
        vf->next=vf2;
657
 
        flags=vf->next->query_format(vf->next,outfmt);
658
 
        if(!flags){
659
 
            mp_tmsg(MSGT_VFILTER,MSGL_ERR,"Cannot find matching colorspace, even by inserting 'scale' :(\n");
660
 
            return 0; // FAIL
661
 
        }
662
 
    }
663
 
    mp_msg(MSGT_VFILTER,MSGL_V,"REQ: flags=0x%X  req=0x%X  \n",flags,vf->default_reqs);
664
 
    miss=vf->default_reqs - (flags&vf->default_reqs);
665
 
    if(miss&VFCAP_ACCEPT_STRIDE){
666
 
        // vf requires stride support but vf->next doesn't support it!
667
 
        // let's insert the 'expand' filter, it does the job for us:
668
 
        vf_instance_t* vf2=vf_open_filter(opts, vf->next,"expand",NULL);
669
 
        if(!vf2) return 0; // shouldn't happen!
670
 
        vf->next=vf2;
671
 
    }
672
 
    vf->next->w = width; vf->next->h = height;
673
 
    return vf_config_wrapper(vf->next,width,height,d_width,d_height,voflags,outfmt);
674
 
}
675
 
 
676
 
int vf_next_control(struct vf_instance *vf, int request, void* data){
677
 
    return vf->next->control(vf->next,request,data);
678
 
}
679
 
 
680
 
int vf_next_query_format(struct vf_instance *vf, unsigned int fmt){
681
 
    int flags=vf->next->query_format(vf->next,fmt);
682
 
    if(flags) flags|=vf->default_caps;
 
711
    int flags = vf->next->query_format(vf->next, outfmt);
 
712
    if (!flags) {
 
713
        // hmm. colorspace mismatch!!!
 
714
        // let's insert the 'scale' filter, it does the job for us:
 
715
        vf_instance_t *vf2;
 
716
        if (vf->next->info == &vf_info_scale)
 
717
            return 0;                                // scale->scale
 
718
        vf2 = vf_open_filter(opts, vf->next, "scale", NULL);
 
719
        if (!vf2)
 
720
            return 0;      // shouldn't happen!
 
721
        vf->next = vf2;
 
722
        flags = vf->next->query_format(vf->next, outfmt);
 
723
        if (!flags) {
 
724
            mp_tmsg(MSGT_VFILTER, MSGL_ERR, "Cannot find matching colorspace, "
 
725
                    "even by inserting 'scale' :(\n");
 
726
            return 0; // FAIL
 
727
        }
 
728
    }
 
729
    mp_msg(MSGT_VFILTER, MSGL_V, "REQ: flags=0x%X  req=0x%X  \n",
 
730
           flags, vf->default_reqs);
 
731
    miss = vf->default_reqs - (flags & vf->default_reqs);
 
732
    if (miss & VFCAP_ACCEPT_STRIDE) {
 
733
        // vf requires stride support but vf->next doesn't support it!
 
734
        // let's insert the 'expand' filter, it does the job for us:
 
735
        vf_instance_t *vf2 = vf_open_filter(opts, vf->next, "expand", NULL);
 
736
        if (!vf2)
 
737
            return 0;      // shouldn't happen!
 
738
        vf->next = vf2;
 
739
    }
 
740
    vf->next->w = width;
 
741
    vf->next->h = height;
 
742
    return vf_config_wrapper(vf->next, width, height, d_width, d_height,
 
743
                             voflags, outfmt);
 
744
}
 
745
 
 
746
int vf_next_control(struct vf_instance *vf, int request, void *data)
 
747
{
 
748
    return vf->next->control(vf->next, request, data);
 
749
}
 
750
 
 
751
int vf_next_query_format(struct vf_instance *vf, unsigned int fmt)
 
752
{
 
753
    int flags = vf->next->query_format(vf->next, fmt);
 
754
    if (flags)
 
755
        flags |= vf->default_caps;
683
756
    return flags;
684
757
}
685
758
 
686
 
int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
687
 
    return vf->next->put_image(vf->next,mpi, pts);
 
759
int vf_next_put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
 
760
{
 
761
    return vf->next->put_image(vf->next, mpi, pts);
688
762
}
689
763
 
690
 
void vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
 
764
void vf_next_draw_slice(struct vf_instance *vf, unsigned char **src,
 
765
                        int *stride, int w, int h, int x, int y)
 
766
{
691
767
    if (vf->next->draw_slice) {
692
 
        vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
693
 
        return;
 
768
        vf->next->draw_slice(vf->next, src, stride, w, h, x, y);
 
769
        return;
694
770
    }
695
771
    if (!vf->dmpi) {
696
 
        mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
697
 
        return;
 
772
        mp_msg(MSGT_VFILTER, MSGL_ERR,
 
773
               "draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
 
774
        return;
698
775
    }
699
776
    if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
700
 
        memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
701
 
            src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
702
 
        return;
 
777
        memcpy_pic(vf->dmpi->planes[0] + y * vf->dmpi->stride[0] +
 
778
                       vf->dmpi->bpp / 8 * x,
 
779
                   src[0], vf->dmpi->bpp / 8 * w, h, vf->dmpi->stride[0],
 
780
                   stride[0]);
 
781
        return;
703
782
    }
704
 
    memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
705
 
        w, h, vf->dmpi->stride[0], stride[0]);
706
 
    memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
707
 
        src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
708
 
    memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
709
 
        src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
 
783
    memcpy_pic(vf->dmpi->planes[0] + y * vf->dmpi->stride[0] + x, src[0],
 
784
               w, h, vf->dmpi->stride[0], stride[0]);
 
785
    memcpy_pic(vf->dmpi->planes[1]
 
786
                   + (y >> vf->dmpi->chroma_y_shift) * vf->dmpi->stride[1]
 
787
                   + (x >> vf->dmpi->chroma_x_shift),
 
788
               src[1], w >> vf->dmpi->chroma_x_shift,
 
789
               h >> vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
 
790
    memcpy_pic(vf->dmpi->planes[2]
 
791
                   + (y >> vf->dmpi->chroma_y_shift) * vf->dmpi->stride[2]
 
792
                   + (x >> vf->dmpi->chroma_x_shift),
 
793
               src[2], w >> vf->dmpi->chroma_x_shift,
 
794
               h >> vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
710
795
}
711
796
 
712
797
//============================================================================
713
798
 
714
 
vf_instance_t *append_filters(vf_instance_t* last,
 
799
vf_instance_t *append_filters(vf_instance_t *last,
715
800
                              struct m_obj_settings *vf_settings)
716
801
{
717
 
  struct MPOpts *opts = last->opts;
718
 
  vf_instance_t* vf;
719
 
  int i;
 
802
    struct MPOpts *opts = last->opts;
 
803
    vf_instance_t *vf;
 
804
    int i;
720
805
 
721
 
  if(vf_settings) {
722
 
    // We want to add them in the 'right order'
723
 
    for(i = 0 ; vf_settings[i].name ; i++)
724
 
      /* NOP */;
725
 
    for(i-- ; i >= 0 ; i--) {
726
 
      //printf("Open filter %s\n",vf_settings[i].name);
727
 
      vf = vf_open_filter(opts, last,vf_settings[i].name,vf_settings[i].attribs);
728
 
      if(vf) last=vf;
 
806
    if (vf_settings) {
 
807
        // We want to add them in the 'right order'
 
808
        for (i = 0; vf_settings[i].name; i++)
 
809
            /* NOP */;
 
810
        for (i--; i >= 0; i--) {
 
811
            //printf("Open filter %s\n",vf_settings[i].name);
 
812
            vf = vf_open_filter(opts, last, vf_settings[i].name,
 
813
                                vf_settings[i].attribs);
 
814
            if (vf)
 
815
                last = vf;
 
816
        }
729
817
    }
730
 
  }
731
 
  return last;
 
818
    return last;
732
819
}
733
820
 
734
821
//============================================================================
735
822
 
736
 
void vf_uninit_filter(vf_instance_t* vf){
737
 
    if(vf->uninit) vf->uninit(vf);
 
823
void vf_uninit_filter(vf_instance_t *vf)
 
824
{
 
825
    if (vf->uninit)
 
826
        vf->uninit(vf);
738
827
    free_mp_image(vf->imgctx.static_images[0]);
739
828
    free_mp_image(vf->imgctx.static_images[1]);
740
829
    free_mp_image(vf->imgctx.temp_images[0]);
744
833
    free(vf);
745
834
}
746
835
 
747
 
void vf_uninit_filter_chain(vf_instance_t* vf){
748
 
    while(vf){
749
 
        vf_instance_t* next=vf->next;
750
 
        vf_uninit_filter(vf);
751
 
        vf=next;
 
836
void vf_uninit_filter_chain(vf_instance_t *vf)
 
837
{
 
838
    while (vf) {
 
839
        vf_instance_t *next = vf->next;
 
840
        vf_uninit_filter(vf);
 
841
        vf = next;
752
842
    }
753
843
}
754
844
 
774
864
    if (delta <= 0) {
775
865
        if (p->inpts_prev == MP_NOPTS_VALUE)
776
866
            delta = 0;
777
 
        else if(pts == p->inpts_prev)
 
867
        else if (pts == p->inpts_prev)
778
868
            delta = p->lastdelta;
779
869
        else
780
870
            delta = pts - p->inpts_prev;
781
871
    }
782
 
    //mp_msg(MSGT_VFILTER, MSGL_INFO, "filmdint: (1) inpts %f (delta: %f, increase: %f)\n", pts, delta, delta * increasefactor);
783
872
    p->inpts_prev = pts;
784
873
    p->lastdelta = delta;
785
874
 
786
875
    if (skip_frame)
787
876
        return MP_NOPTS_VALUE;
788
877
 
789
 
    // detect bogus deltas and then passthru pts (possibly caused by seeking, or bad input)
790
 
    if (p->outpts_prev == MP_NOPTS_VALUE || reset_pattern || delta <= 0.0 || delta >= 0.5) {
 
878
    /* detect bogus deltas and then passthru pts (possibly caused by seeking,
 
879
     * or bad input) */
 
880
    if (p->outpts_prev == MP_NOPTS_VALUE || reset_pattern || delta <= 0.0 ||
 
881
            delta >= 0.5)
791
882
        newpts = pts;
792
 
    } else {
 
883
    else {
793
884
        // turn 5 frames into 4
794
885
        newpts = p->outpts_prev + delta * increasefactor;
795
886
 
805
896
        if (newpts > pts + delta * boundfactor_plus)
806
897
            newpts = pts + delta * boundfactor_plus;
807
898
        if (newpts < p->outpts_prev)
808
 
            newpts = p->outpts_prev; // damage control
 
899
            newpts = p->outpts_prev;  // damage control
809
900
    }
810
 
    //mp_msg(MSGT_VFILTER, MSGL_INFO, "filmdint: (2) outpts %f (delta: %f)\n", newpts, newpts - p->outpts_prev);
811
901
    p->outpts_prev = newpts;
812
902
 
813
903
    return newpts;