Exemple #1
0
/* Copy YV12 images */
static void
copy_image_YV12(
    GstVaapiImageRaw        *dst_image,
    GstVaapiImageRaw        *src_image,
    const GstVaapiRectangle *rect
)
{
    guchar *dst, *src;
    guint dst_stride, src_stride;
    guint i, x, y, w, h;

    /* Y plane */
    dst_stride = dst_image->stride[0];
    dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
    src_stride = src_image->stride[0];
    src = src_image->pixels[0] + rect->y * src_stride + rect->x;
    memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);

    /* U/V planes */
    x = rect->x / 2;
    y = rect->y / 2;
    w = rect->width / 2;
    h = rect->height / 2;
    for (i = 1; i < dst_image->num_planes; i++) {
        dst_stride = dst_image->stride[i];
        dst = dst_image->pixels[i] + y * dst_stride + x;
        src_stride = src_image->stride[i];
        src = src_image->pixels[i] + y * src_stride + x;
        memcpy_pic(dst, dst_stride, src, src_stride, w, h);
    }
}
Exemple #2
0
/** @brief libvo Callback: Draw slice
 *  @return 0 on success
 */
static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y )
{
    char *my_src;   /**< Pointer to the source image */
    char *dst;      /**< Pointer to the destination image */
    int  uv_stride; /**< Stride of the U/V planes */

    /* If the D3D device is uncooperative (not initialized), return success.
       The device will be probed for reinitialization in the next flip_page() */
    if (!priv->d3d_device)
        return 0;

    /* Lock the offscreen surface if it's not already locked. */
    if (!priv->locked_rect.pBits) {
        if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
                                              &priv->locked_rect, NULL, 0))) {
            mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface lock failure.\n");
            return VO_FALSE;
        }
    }

    uv_stride = priv->locked_rect.Pitch / 2;

    /* Copy Y */
    dst = priv->locked_rect.pBits;
    dst = dst + priv->locked_rect.Pitch * y + x;
    my_src = src[0];
    memcpy_pic(dst, my_src, w, h, priv->locked_rect.Pitch, stride[0]);

    w /= 2;
    h /= 2;
    x /= 2;
    y /= 2;

    /* Copy U */
    dst = priv->locked_rect.pBits;
    dst = dst + priv->locked_rect.Pitch * priv->src_height
          + uv_stride * y + x;
    if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2'))
        my_src = src[2];
    else
        my_src = src[1];

    memcpy_pic(dst, my_src, w, h, uv_stride, stride[1]);

    /* Copy V */
    dst = priv->locked_rect.pBits;
    dst = dst + priv->locked_rect.Pitch * priv->src_height
          + uv_stride * (priv->src_height / 2) + uv_stride * y + x;
    if (priv->movie_src_fmt == MAKEFOURCC('Y','V','1','2'))
        my_src=src[1];
    else
        my_src=src[2];

    memcpy_pic(dst, my_src, w, h, uv_stride, stride[2]);

    return 0; /* Success */
}
Exemple #3
0
void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi) {
  if(mpi->flags&MP_IMGFLAG_PLANAR){
    memcpy_pic(dmpi->planes[0],mpi->planes[0], mpi->w, mpi->h,
	       dmpi->stride[0],mpi->stride[0]);
    memcpy_pic(dmpi->planes[1],mpi->planes[1], mpi->chroma_width, mpi->chroma_height,
	       dmpi->stride[1],mpi->stride[1]);
    memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height,
	       dmpi->stride[2],mpi->stride[2]);
  } else {
    memcpy_pic(dmpi->planes[0],mpi->planes[0],
	       mpi->w*(dmpi->bpp/8), mpi->h,
	       dmpi->stride[0],mpi->stride[0]);
  }
}
Exemple #4
0
/**
 * \brief Removes the logo from a plane (either luma or chroma).
 *
 * \param vf Not needed by this function, but needed by the blur function.
 * \param source The image to have it's logo removed.
 * \param destination Where the output image will be stored.
 * \param source_stride How far apart (in memory) two consecutive lines are.
 * \param destination Same as source_stride, but for the destination image.
 * \param width Width of the image. This is the same for source and destination.
 * \param height Height of the image. This is the same for source and destination.
 * \param is_image_direct If the image is direct, then source and destination are
 *        the same and we can save a lot of time by not copying pixels that
 *        haven't changed.
 * \param filter The image that stores the distance to the edge of the logo for
 *        each pixel.
 * \param logo_start_x Smallest x-coordinate that contains at least 1 logo pixel.
 * \param logo_start_y Smallest y-coordinate that contains at least 1 logo pixel.
 * \param logo_end_x Largest x-coordinate that contains at least 1 logo pixel.
 * \param logo_end_y Largest y-coordinate that contains at least 1 logo pixel.
 *
 * This function processes an entire plane. Pixels outside of the logo are copied
 * to the output without change, and pixels inside the logo have the de-blurring
 * function applied.
 */
static void convert_yv12(const vf_instance_t * const vf, const char * const source, const int source_stride,
                         const mp_image_t * const source_image, const int width, const int height,
                         char * const destination, const int destination_stride, int is_image_direct, pgm_structure * filter,
                         const int plane, const int logo_start_x, const int logo_start_y, const int logo_end_x, const int logo_end_y)
{
  int y;
  int x;

  /* These pointers point to where we are getting our pixel data (inside mpi) and where we are storing it (inside dmpi). */
  const unsigned char * source_line;
  unsigned char * destination_line;

  if (!is_image_direct)
    memcpy_pic(destination, source, width, height, destination_stride, source_stride);

  for (y = logo_start_y; y <= logo_end_y; y++)
  {
    source_line = (const unsigned char *) source + (source_stride * y);
    destination_line = (unsigned char *) destination + (destination_stride * y);

    for (x = logo_start_x; x <= logo_end_x; x++)
    {
      unsigned int output;

      if (filter->pixel[(y * filter->width) + x]) /* Only process if we are in the logo. */
      {
        get_blur(vf, &output, filter, source_image, x, y, plane);
        destination_line[x] = output;
      }
      else /* Else just copy the data. */
        if (!is_image_direct)
          destination_line[x] = source_line[x];
    }
  }
}
Exemple #5
0
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
    mp_image_t *dmpi;

    if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
        // no DR, so get a new image! hope we'll get DR buffer:
        dmpi=ff_vf_get_image(vf->next,mpi->imgfmt,
            MP_IMGTYPE_TEMP,
            MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
            mpi->width,mpi->height);
        ff_vf_clone_mpi_attributes(dmpi, mpi);
    }else{
        dmpi=vf->dmpi;
    }

    vf->priv->mpeg2= mpi->qscale_type;
    if(vf->priv->log2_count || !(mpi->flags&MP_IMGFLAG_DIRECT)){
        if(mpi->qscale || vf->priv->qp){
            filter(vf->priv, dmpi->planes, mpi->planes, dmpi->stride, mpi->stride, mpi->w, mpi->h, mpi->qscale, mpi->qstride);
        }else{
            memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0], mpi->stride[0]);
            memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[1], mpi->stride[1]);
            memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
        }
    }

#if HAVE_MMX
    if(ff_gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
#endif
#if HAVE_MMX2
    if(ff_gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
#endif

    return ff_vf_next_put_image(vf,dmpi, pts);
}
Exemple #6
0
static void flip_page(void)
{
#ifndef USE_CONVERT2FB
	int out_offset = 0, in_offset = 0;

	memcpy_pic(center + out_offset, next_frame + in_offset,
	           in_width * fb_pixel_size, in_height,
	           fb_line_len, in_width * fb_pixel_size);
#endif
}
Exemple #7
0
//Exact copy of vf.c
void ff_vf_next_draw_slice(struct vf_instance *vf,unsigned char** src, int * stride,int w, int h, int x, int y){
    if (vf->next->draw_slice) {
        vf->next->draw_slice(vf->next,src,stride,w,h,x,y);
        return;
    }
    if (!vf->dmpi) {
        ff_mp_msg(MSGT_VFILTER,MSGL_ERR,"draw_slice: dmpi not stored by vf_%s\n", vf->info->name);
        return;
    }
    if (!(vf->dmpi->flags & MP_IMGFLAG_PLANAR)) {
        memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+vf->dmpi->bpp/8*x,
            src[0], vf->dmpi->bpp/8*w, h, vf->dmpi->stride[0], stride[0]);
        return;
    }
    memcpy_pic(vf->dmpi->planes[0]+y*vf->dmpi->stride[0]+x, src[0],
        w, h, vf->dmpi->stride[0], stride[0]);
    memcpy_pic(vf->dmpi->planes[1]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[1]+(x>>vf->dmpi->chroma_x_shift),
        src[1], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[1], stride[1]);
    memcpy_pic(vf->dmpi->planes[2]+(y>>vf->dmpi->chroma_y_shift)*vf->dmpi->stride[2]+(x>>vf->dmpi->chroma_x_shift),
        src[2], w>>vf->dmpi->chroma_x_shift, h>>vf->dmpi->chroma_y_shift, vf->dmpi->stride[2], stride[2]);
}
Exemple #8
0
static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
{
	uint8_t *in = src[0];
#ifdef USE_CONVERT2FB
	uint8_t *dest = center + (fb_line_len * y) + (x * fb_pixel_size);
	int next = fb_line_len;
#else
	uint8_t *dest = next_frame + (in_width * y + x) * fb_pixel_size;
	int next = in_width * fb_pixel_size;
#endif

	memcpy_pic(dest, in, w * fb_pixel_size, h, next, stride[0]);
	return 0;
}
Exemple #9
0
/* Copy NV12 images */
static void
copy_image_NV12(
    GstVaapiImageRaw        *dst_image,
    GstVaapiImageRaw        *src_image,
    const GstVaapiRectangle *rect
)
{
    guchar *dst, *src;
    guint dst_stride, src_stride;

    /* Y plane */
    dst_stride = dst_image->stride[0];
    dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
    src_stride = src_image->stride[0];
    src = src_image->pixels[0] + rect->y * src_stride + rect->x;
    memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height);

    /* UV plane */
    dst_stride = dst_image->stride[1];
    dst = dst_image->pixels[1] + (rect->y / 2) * dst_stride + (rect->x & -2);
    src_stride = src_image->stride[1];
    src = src_image->pixels[1] + (rect->y / 2) * src_stride + (rect->x & -2);
    memcpy_pic(dst, dst_stride, src, src_stride, rect->width, rect->height / 2);
}
Exemple #10
0
/* Copy RGBA images */
static void
copy_image_RGBA(
    GstVaapiImageRaw        *dst_image,
    GstVaapiImageRaw        *src_image,
    const GstVaapiRectangle *rect
)
{
    guchar *dst, *src;
    guint dst_stride, src_stride;

    dst_stride = dst_image->stride[0];
    dst = dst_image->pixels[0] + rect->y * dst_stride + rect->x;
    src_stride = src_image->stride[0];
    src = src_image->pixels[0] + rect->y * src_stride + rect->x;
    memcpy_pic(dst, dst_stride, src, src_stride, 4 * rect->width, rect->height);
}
Exemple #11
0
static int
put_image(struct vf_instance *vf, mp_image_t* mpi, double pts){
    mp_image_t* dmpi;
    unsigned int bpp = mpi->bpp / 8;
    int x, y, w, h;
    dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_TEMP,
                        MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
                        mpi->w, mpi->h);

    memcpy_pic(dmpi->planes[0],mpi->planes[0],mpi->w*bpp, mpi->h,
               dmpi->stride[0],mpi->stride[0]);
    if(mpi->flags&MP_IMGFLAG_PLANAR && mpi->flags&MP_IMGFLAG_YUV){
        memcpy_pic(dmpi->planes[1],mpi->planes[1],
                   mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift,
                   dmpi->stride[1],mpi->stride[1]);
        memcpy_pic(dmpi->planes[2],mpi->planes[2],
                   mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift,
                   dmpi->stride[2],mpi->stride[2]);
    }
Exemple #12
0
static uint32_t draw_image(mp_image_t *mpi){
  int buf = 0;
  tdfx_vid_agp_move_t mov;
  tdfx_vid_yuv_t yuv;
  int p;
  uint8_t* planes[3];

#ifdef VERBOSE
  printf("Draw image %d\n",buf);
#endif

  if(mpi->flags & MP_IMGFLAG_DIRECT)
    buf = (int)mpi->priv;

  switch(mpi->imgfmt) {
  case IMGFMT_YUY2:
  case IMGFMT_UYVY:
  case IMGFMT_BGR8:
  case IMGFMT_BGR15:
  case IMGFMT_BGR16:
  case IMGFMT_BGR24:
  case IMGFMT_BGR32:
    if(!(mpi->flags&(MP_IMGFLAG_DIRECT|MP_IMGFLAG_DRAW_CALLBACK))) {
      // copy to agp_mem
#ifdef VERBOSE
      printf("Memcpy\n");
#endif
      planes[0] = agp_mem + buf * buffer_size;
      mem2agpcpy_pic(planes[0],mpi->planes[0],src_bpp*mpi->width,mpi->height,
		     buffer_stride[0],mpi->stride[0]);
    } else
      planes[0] = agp_mem + buf * buffer_size;

    mov.move2 = TDFX_VID_MOVE_2_PACKED;
    mov.width = mpi->width*((mpi->bpp+7)/8);
    mov.height = mpi->height;
    mov.src = planes[0] - agp_mem;
    mov.src_stride = buffer_stride[0];

    mov.dst = back_buffer;
    mov.dst_stride = src_stride;

    if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov))
      mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_TDFXVID_AgpMoveFailed);
    break;

  case IMGFMT_YV12:
  case IMGFMT_I420:
    if(!(mpi->flags&(MP_IMGFLAG_DIRECT|MP_IMGFLAG_DRAW_CALLBACK))) {
      // Copy to agp mem
#ifdef VERBOSE
      printf("Memcpy\n");
#endif
      planes[0] = agp_mem + buf * buffer_size;
      memcpy_pic(planes[0],mpi->planes[0],mpi->width,mpi->height,
		 buffer_stride[0],mpi->stride[0]);
      planes[1] = planes[0] + (mpi->height*mpi->stride[0]);
      memcpy_pic(planes[1],mpi->planes[1],mpi->chroma_width,mpi->chroma_height,
		 buffer_stride[1],mpi->stride[1]);
      planes[2] = planes[1] + (mpi->chroma_height*mpi->stride[1]);
      memcpy_pic(planes[2],mpi->planes[2],mpi->chroma_width,mpi->chroma_height,
		 buffer_stride[2],mpi->stride[2]);
    } else {
      planes[0] = agp_mem + buf * buffer_size;
      planes[1] = planes[0] + buffer_stride[0] * src_height;
      planes[2] = planes[1] + buffer_stride[1] * src_height/2;
    }

    // Setup the yuv thing
    yuv.base = back_buffer;
    yuv.stride = src_stride;
    if(ioctl(tdfx_fd,TDFX_VID_SET_YUV,&yuv)) {
      mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_TDFXVID_SetYuvFailed);
      break;
    }


    // Now agp move that
    // Y
    mov.move2 = TDFX_VID_MOVE_2_YUV;
    mov.width = mpi->width;
    mov.height = mpi->height;
    mov.src = planes[0] - agp_mem;
    mov.src_stride =  buffer_stride[0];
    mov.dst = 0x0;
    mov.dst_stride = TDFX_VID_YUV_STRIDE;

    if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) {
      mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnYPlane);
      break;
    }
    //return 0;
    // U
    p = mpi->imgfmt == IMGFMT_YV12 ? 1 : 2;
    mov.width = mpi->chroma_width;
    mov.height = mpi->chroma_height;
    mov.src = planes[p] - agp_mem;
    mov.src_stride = buffer_stride[p];
    mov.dst += TDFX_VID_YUV_PLANE_SIZE;
    if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) {
      mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnUPlane);
      break;
    }
    // V
    p = mpi->imgfmt == IMGFMT_YV12 ? 2 : 1;
    mov.src = planes[p] - agp_mem;
    mov.src_stride = buffer_stride[p];
    mov.dst += TDFX_VID_YUV_PLANE_SIZE;
    if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) {
      mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_TDFXVID_AgpMoveFailedOnVPlane);
      break;
    }
    break;
  default:
    mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_TDFXVID_UnknownFormat,mpi->imgfmt);
    return VO_TRUE;
  }

  return VO_TRUE;
}
Exemple #13
0
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
    int ret = 0;
    mp_image_t *dmpi;

    switch (vf->priv->mode) {
    case 0:
        dmpi = vf->priv->dmpi;
        if (dmpi == NULL) {
            dmpi = ff_vf_get_image(vf->next, mpi->imgfmt,
                        MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
                        MP_IMGFLAG_PRESERVE,
                        mpi->width, mpi->height*2);

            vf->priv->dmpi = dmpi;

            memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
                   dmpi->stride[0]*2, mpi->stride[0]);
            if (mpi->flags & MP_IMGFLAG_PLANAR) {
                memcpy_pic(dmpi->planes[1], mpi->planes[1],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[1]*2, mpi->stride[1]);
                memcpy_pic(dmpi->planes[2], mpi->planes[2],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[2]*2, mpi->stride[2]);
            }
        } else {
            vf->priv->dmpi = NULL;

            memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0], mpi->w, mpi->h,
                   dmpi->stride[0]*2, mpi->stride[0]);
            if (mpi->flags & MP_IMGFLAG_PLANAR) {
                memcpy_pic(dmpi->planes[1]+dmpi->stride[1], mpi->planes[1],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[1]*2, mpi->stride[1]);
                memcpy_pic(dmpi->planes[2]+dmpi->stride[2], mpi->planes[2],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[2]*2, mpi->stride[2]);
            }
            ret = ff_vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
        }
        break;
    case 1:
        if (vf->priv->frame & 1)
            ret = ff_vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
        break;
    case 2:
        if ((vf->priv->frame & 1) == 0)
            ret = ff_vf_next_put_image(vf, mpi, MP_NOPTS_VALUE);
        break;
    case 3:
        dmpi = ff_vf_get_image(vf->next, mpi->imgfmt,
                    MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
                    mpi->width, mpi->height*2);
        /* fixme, just clear alternate lines */
        ff_vf_mpi_clear(dmpi, 0, 0, dmpi->w, dmpi->h);
        if ((vf->priv->frame & 1) == 0) {
            memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h,
                   dmpi->stride[0]*2, mpi->stride[0]);
            if (mpi->flags & MP_IMGFLAG_PLANAR) {
                memcpy_pic(dmpi->planes[1], mpi->planes[1],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[1]*2, mpi->stride[1]);
                memcpy_pic(dmpi->planes[2], mpi->planes[2],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[2]*2, mpi->stride[2]);
            }
        } else {
            memcpy_pic(dmpi->planes[0]+dmpi->stride[0], mpi->planes[0], mpi->w, mpi->h,
                   dmpi->stride[0]*2, mpi->stride[0]);
            if (mpi->flags & MP_IMGFLAG_PLANAR) {
                memcpy_pic(dmpi->planes[1]+dmpi->stride[1], mpi->planes[1],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[1]*2, mpi->stride[1]);
                memcpy_pic(dmpi->planes[2]+dmpi->stride[2], mpi->planes[2],
                       mpi->chroma_width, mpi->chroma_height,
                       dmpi->stride[2]*2, mpi->stride[2]);
            }
        }
        ret = ff_vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
        break;
    case 4:
        // Interleave even lines (only) from Frame 'i' with odd
        // lines (only) from Frame 'i+1', halving the Frame
        // rate and preserving image height.

        dmpi = vf->priv->dmpi;

        // @@ Need help:  Should I set dmpi->fields to indicate
        // that the (new) frame will be interlaced!?  E.g. ...
        // dmpi->fields |= MP_IMGFIELD_INTERLACED;
        // dmpi->fields |= MP_IMGFIELD_TOP_FIRST;
        // etc.

        if (dmpi == NULL) {
            dmpi = ff_vf_get_image(vf->next, mpi->imgfmt,
                        MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
                        MP_IMGFLAG_PRESERVE,
                        mpi->width, mpi->height);

            vf->priv->dmpi = dmpi;

            my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2,
                      dmpi->stride[0]*2, mpi->stride[0]*2);
            if (mpi->flags & MP_IMGFLAG_PLANAR) {
                my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
                          mpi->chroma_width, mpi->chroma_height/2,
                          dmpi->stride[1]*2, mpi->stride[1]*2);
                my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
                          mpi->chroma_width, mpi->chroma_height/2,
                          dmpi->stride[2]*2, mpi->stride[2]*2);
            }
        } else {
            vf->priv->dmpi = NULL;

            my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
                      mpi->planes[0]+mpi->stride[0],
                      mpi->w, mpi->h/2,
                      dmpi->stride[0]*2, mpi->stride[0]*2);
            if (mpi->flags & MP_IMGFLAG_PLANAR) {
                my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
                          mpi->planes[1]+mpi->stride[1],
                          mpi->chroma_width, mpi->chroma_height/2,
                          dmpi->stride[1]*2, mpi->stride[1]*2);
                my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
                          mpi->planes[2]+mpi->stride[2],
                          mpi->chroma_width, mpi->chroma_height/2,
                          dmpi->stride[2]*2, mpi->stride[2]*2);
            }
            ret = ff_vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
        }
        break;
    }

    vf->priv->frame++;

    return ret;
}
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
	struct pullup_context *c = vf->priv->ctx;
	struct pullup_buffer *b;
	struct pullup_frame *f;
	mp_image_t *dmpi;
	int ret;
	int p;
	int i;

	if (!vf->priv->init) init_pullup(vf, mpi);

	if (mpi->flags & MP_IMGFLAG_DIRECT) {
		b = mpi->priv;
		mpi->priv = 0;
	} else {
		b = pullup_get_buffer(c, 2);
		if (!b) {
			mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n");
			f = pullup_get_frame(c);
			pullup_release_frame(f);
			return 0;
		}
		memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h,
			c->stride[0], mpi->stride[0]);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			memcpy_pic(b->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height,
				c->stride[1], mpi->stride[1]);
			memcpy_pic(b->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height,
				c->stride[2], mpi->stride[2]);
		}
	}
	if (mpi->qscale) {
		fast_memcpy(b->planes[3], mpi->qscale, c->w[3]);
		fast_memcpy(b->planes[3]+c->w[3], mpi->qscale, c->w[3]);
	}

	p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 :
		(mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0);
	pullup_submit_field(c, b, p);
	pullup_submit_field(c, b, p^1);
	if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST)
		pullup_submit_field(c, b, p);

	pullup_release_buffer(b, 2);

	f = pullup_get_frame(c);

	/* Fake yes for first few frames (buffer depth) to keep from
	 * breaking A/V sync with G1's bad architecture... */
	if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;

	if (f->length < 2) {
		pullup_release_frame(f);
		f = pullup_get_frame(c);
		if (!f) return 0;
		if (f->length < 2) {
			pullup_release_frame(f);
			if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
				return 0;
			f = pullup_get_frame(c);
			if (!f) return 0;
			if (f->length < 2) {
				pullup_release_frame(f);
				return 0;
			}
		}
	}

#if 0
	/* Average qscale tables from both frames. */
	if (mpi->qscale) {
		for (i=0; i<c->w[3]; i++) {
			vf->priv->qbuf[i] = (f->ofields[0]->planes[3][i]
				+ f->ofields[1]->planes[3][i+c->w[3]])>>1;
		}
	}
#else
	/* Take worst of qscale tables from both frames. */
	if (mpi->qscale) {
		for (i=0; i<c->w[3]; i++) {
			vf->priv->qbuf[i] = MAX(f->ofields[0]->planes[3][i], f->ofields[1]->planes[3][i+c->w[3]]);
		}
	}
#endif

	/* If the frame isn't already exportable... */
	while (!f->buffer) {
		dmpi = vf_get_image(vf->next, mpi->imgfmt,
			MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
			mpi->width, mpi->height);
		/* FIXME: Is it ok to discard dmpi if it's not direct? */
		if (!(dmpi->flags & MP_IMGFLAG_DIRECT)) {
			pullup_pack_frame(c, f);
			break;
		}
		/* Direct render fields into output buffer */
		my_memcpy_pic(dmpi->planes[0], f->ofields[0]->planes[0],
			mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
		my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0],
			f->ofields[1]->planes[0] + c->stride[0],
			mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2);
		if (mpi->flags & MP_IMGFLAG_PLANAR) {
			my_memcpy_pic(dmpi->planes[1], f->ofields[0]->planes[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, c->stride[1]*2);
			my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1],
				f->ofields[1]->planes[1] + c->stride[1],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[1]*2, c->stride[1]*2);
			my_memcpy_pic(dmpi->planes[2], f->ofields[0]->planes[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, c->stride[2]*2);
			my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2],
				f->ofields[1]->planes[2] + c->stride[2],
				mpi->chroma_width, mpi->chroma_height/2,
				dmpi->stride[2]*2, c->stride[2]*2);
		}
		pullup_release_frame(f);
		if (mpi->qscale) {
			dmpi->qscale = vf->priv->qbuf;
			dmpi->qstride = mpi->qstride;
			dmpi->qscale_type = mpi->qscale_type;
		}
		return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
	}
	dmpi = vf_get_image(vf->next, mpi->imgfmt,
		MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE,
		mpi->width, mpi->height);

	dmpi->planes[0] = f->buffer->planes[0];
	dmpi->planes[1] = f->buffer->planes[1];
	dmpi->planes[2] = f->buffer->planes[2];

	dmpi->stride[0] = c->stride[0];
	dmpi->stride[1] = c->stride[1];
	dmpi->stride[2] = c->stride[2];

	if (mpi->qscale) {
		dmpi->qscale = vf->priv->qbuf;
		dmpi->qstride = mpi->qstride;
		dmpi->qscale_type = mpi->qscale_type;
	}
	ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
	pullup_release_frame(f);
	return ret;
}
Exemple #15
0
static int
put_image(struct vf_instance* vf, mp_image_t* mpi, double pts){
	int buf_x=0, buf_y=0, buf_pos=0;
	int have, got, want;
	int xpos=0, ypos=0, pos=0;
	unsigned char red=0, green=0, blue=0;
	int  alpha;
	mp_image_t* dmpi;

    dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_TEMP,
						MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
						mpi->w, mpi->h);

    memcpy_pic( dmpi->planes[0], mpi->planes[0], mpi->width, mpi->height, dmpi->stride[0], mpi->stride[0] );
    memcpy_pic( dmpi->planes[1], mpi->planes[1], mpi->chroma_width, mpi->chroma_height, dmpi->stride[1], mpi->stride[1] );
    memcpy_pic( dmpi->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height, dmpi->stride[2], mpi->stride[2] );

    if(vf->priv->stream_fd >= 0) {
		struct timeval tv;
		int ready;

		FD_SET( vf->priv->stream_fd, &vf->priv->stream_fdset );
		tv.tv_sec=0; tv.tv_usec=0;

		ready = select( vf->priv->stream_fd+1, &vf->priv->stream_fdset, NULL, NULL, &tv );
		if(ready > 0) {
			// We've got new data from the FIFO

			char cmd[20], args[100];
			int  imgw,imgh,imgx,imgy,clear,imgalpha,pxsz=1,command;
			unsigned char *buffer = NULL;

			if(! _read_cmd( vf->priv->stream_fd, cmd, args) ) {
				mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl: Error reading commands: %s\n\n", strerror(errno));
				return FALSE;
			}
			mp_msg(MSGT_VFILTER, MSGL_DBG2, "\nDEBUG: Got: %s+%s\n", cmd, args);

			command=NONE;
			if     ( strncmp(cmd,"RGBA32",6)==0 ) { pxsz=4; command = IMG_RGBA32; }
			else if( strncmp(cmd,"ABGR32",6)==0 ) { pxsz=4; command = IMG_ABGR32; }
			else if( strncmp(cmd,"RGB24" ,5)==0 ) { pxsz=3; command = IMG_RGB24;  }
			else if( strncmp(cmd,"BGR24" ,5)==0 ) { pxsz=3; command = IMG_BGR24;  }
			else if( strncmp(cmd,"CLEAR" ,5)==0 ) { pxsz=1; command = CMD_CLEAR;  }
			else if( strncmp(cmd,"ALPHA" ,5)==0 ) { pxsz=1; command = CMD_ALPHA;  }
			else if( strncmp(cmd,"OPAQUE",6)==0 ) vf->priv->opaque=TRUE;
			else if( strncmp(cmd,"SHOW",  4)==0 ) vf->priv->hidden=FALSE;
			else if( strncmp(cmd,"HIDE",  4)==0 ) vf->priv->hidden=TRUE;
			else if( strncmp(cmd,"FLUSH" ,5)==0 ) return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
			else {
			    mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl: Unknown command: '%s'. Ignoring.\n", cmd);
			    return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
			}

			if(command == CMD_ALPHA) {
				sscanf( args, "%d %d %d %d %d", &imgw, &imgh, &imgx, &imgy, &imgalpha);
				mp_msg(MSGT_VFILTER, MSGL_DBG2, "\nDEBUG: ALPHA: %d %d %d %d %d\n\n",
					imgw, imgh, imgx, imgy, imgalpha);
				if(imgw==0 && imgh==0) vf->priv->opaque=FALSE;
			}

			if(command & IS_RAWIMG) {
				sscanf( args, "%d %d %d %d %d %d",
					&imgw, &imgh, &imgx, &imgy, &imgalpha, &clear);
				mp_msg(MSGT_VFILTER, MSGL_DBG2, "\nDEBUG: RAWIMG: %d %d %d %d %d %d\n\n",
					imgw, imgh, imgx, imgy, imgalpha, clear);

			    buffer = malloc(imgw*imgh*pxsz);
			    if(!buffer) {
			    	mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl: Couldn't allocate temporary buffer! Skipping...\n\n");
					return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
			    }
  				/* pipes/sockets might need multiple calls to read(): */
			    want = (imgw*imgh*pxsz);
			    have = 0;
			    while (have < want) {
				got = read( vf->priv->stream_fd, buffer+have, want-have );
				if (got == 0) {
			    	    mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl: premature EOF...\n\n");
				    break;
				}
				if (got < 0) {
			    	    mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl: read error: %s\n\n", strerror(errno));
				    break;
				}
				have += got;
			    }
			    mp_msg(MSGT_VFILTER, MSGL_DBG2, "Got %d bytes... (wanted %d)\n", have, want );

				if(clear) {
					memset( vf->priv->bitmap.y,   0, vf->priv->w*vf->priv->h );
					memset( vf->priv->bitmap.u, 128, vf->priv->w*vf->priv->h/4 );
					memset( vf->priv->bitmap.v, 128, vf->priv->w*vf->priv->h/4 );
					memset( vf->priv->bitmap.a,   0, vf->priv->w*vf->priv->h );
					memset( vf->priv->bitmap.oa,  0, vf->priv->w*vf->priv->h );
					vf->priv->x1 = dmpi->width;
					vf->priv->y1 = dmpi->height;
					vf->priv->x2 = vf->priv->y2 = 0;
				}
				// Define how much of our bitmap that contains graphics!
				vf->priv->x1 = av_clip(imgx, 0, vf->priv->x1);
				vf->priv->y1 = av_clip(imgy, 0, vf->priv->y1);
				vf->priv->x2 = av_clip(imgx + imgw, vf->priv->x2, vf->priv->w);
				vf->priv->y2 = av_clip(imgy + imgh, vf->priv->y2, vf->priv->h);
			}

			if( command == CMD_CLEAR ) {
				sscanf( args, "%d %d %d %d", &imgw, &imgh, &imgx, &imgy);
				mp_msg(MSGT_VFILTER, MSGL_DBG2, "\nDEBUG: CLEAR: %d %d %d %d\n\n", imgw, imgh, imgx, imgy);

				for( ypos=imgy ; (ypos < (imgy+imgh)) && (ypos < vf->priv->y2) ; ypos++ ) {
					memset( vf->priv->bitmap.y  + (ypos*vf->priv->w) + imgx, 0, imgw );
					memset( vf->priv->bitmap.a  + (ypos*vf->priv->w) + imgx, 0, imgw );
					memset( vf->priv->bitmap.oa + (ypos*vf->priv->w) + imgx, 0, imgw );
					if(ypos%2) {
						memset( vf->priv->bitmap.u + ((ypos/2)*dmpi->stride[1]) + (imgx/2), 128, imgw/2 );
						memset( vf->priv->bitmap.v + ((ypos/2)*dmpi->stride[2]) + (imgx/2), 128, imgw/2 );
					}
				}	// Recalculate area that contains graphics
				if( (imgx <= vf->priv->x1) && ( (imgw+imgx) >= vf->priv->x2) ) {
					if( (imgy <= vf->priv->y1) && ( (imgy+imgh) >= vf->priv->y1) )
						vf->priv->y1 = imgy+imgh;
					if( (imgy <= vf->priv->y2) && ( (imgy+imgh) >= vf->priv->y2) )
						vf->priv->y2 = imgy;
				}
				if( (imgy <= vf->priv->y1) && ( (imgy+imgh) >= vf->priv->y2) ) {
					if( (imgx <= vf->priv->x1) && ( (imgx+imgw) >= vf->priv->x1) )
						vf->priv->x1 = imgx+imgw;
					if( (imgx <= vf->priv->x2) && ( (imgx+imgw) >= vf->priv->x2) )
						vf->priv->x2 = imgx;
				}
				return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
			}

			for( buf_y=0 ; (buf_y < imgh) && (buf_y < (vf->priv->h-imgy)) ; buf_y++ ) {
			    for( buf_x=0 ; (buf_x < (imgw*pxsz)) && (buf_x < ((vf->priv->w+imgx)*pxsz)) ; buf_x += pxsz ) {
					if(command & IS_RAWIMG) buf_pos = (buf_y * imgw * pxsz) + buf_x;
					pos = ((buf_y+imgy) * vf->priv->w) + ((buf_x/pxsz)+imgx);

					switch(command) {
						case IMG_RGBA32:
							red   = buffer[buf_pos+0];
							green = buffer[buf_pos+1];
							blue  = buffer[buf_pos+2];
							alpha = buffer[buf_pos+3];
							break;
						case IMG_ABGR32:
							alpha = buffer[buf_pos+0];
							blue  = buffer[buf_pos+1];
							green = buffer[buf_pos+2];
							red   = buffer[buf_pos+3];
							break;
						case IMG_RGB24:
							red   = buffer[buf_pos+0];
							green = buffer[buf_pos+1];
							blue  = buffer[buf_pos+2];
							alpha = 0xFF;
		    				break;
						case IMG_BGR24:
							blue  = buffer[buf_pos+0];
							green = buffer[buf_pos+1];
							red   = buffer[buf_pos+2];
							alpha = 0xFF;
		    				break;
						case CMD_ALPHA:
							vf->priv->bitmap.a[pos] = INRANGE((vf->priv->bitmap.oa[pos]+imgalpha),0,255);
							break;
						default:
					   		mp_msg(MSGT_VFILTER, MSGL_ERR, "vf_bmovl: Internal error!\n");
							return FALSE;
					}
					if( command & IS_RAWIMG ) {
						vf->priv->bitmap.y[pos]  = rgb2y(red,green,blue);
						vf->priv->bitmap.oa[pos] = alpha;
						vf->priv->bitmap.a[pos]  = INRANGE((alpha+imgalpha),0,255);
						if((buf_y%2) && ((buf_x/pxsz)%2)) {
							pos = ( ((buf_y+imgy)/2) * dmpi->stride[1] ) + (((buf_x/pxsz)+imgx)/2);
							vf->priv->bitmap.u[pos] = rgb2u(red,green,blue);
							vf->priv->bitmap.v[pos] = rgb2v(red,green,blue);
						}
					}
				} // for buf_x
			} // for buf_y
			free (buffer);
		} else if(ready < 0) {
			mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl: Error %d in fifo: %s\n\n", errno, strerror(errno));
		}
    }

	if(vf->priv->hidden) return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);

	if(vf->priv->opaque) {	// Just copy buffer memory to screen
		for( ypos=vf->priv->y1 ; ypos < vf->priv->y2 ; ypos++ ) {
			fast_memcpy( dmpi->planes[0] + (ypos*dmpi->stride[0]) + vf->priv->x1,
			        vf->priv->bitmap.y + (ypos*vf->priv->w) + vf->priv->x1,
					vf->priv->x2 - vf->priv->x1 );
			if(ypos%2) {
				fast_memcpy( dmpi->planes[1] + ((ypos/2)*dmpi->stride[1]) + (vf->priv->x1/2),
				        vf->priv->bitmap.u + (((ypos/2)*(vf->priv->w)/2)) + (vf->priv->x1/2),
				        (vf->priv->x2 - vf->priv->x1)/2 );
				fast_memcpy( dmpi->planes[2] + ((ypos/2)*dmpi->stride[2]) + (vf->priv->x1/2),
				        vf->priv->bitmap.v + (((ypos/2)*(vf->priv->w)/2)) + (vf->priv->x1/2),
				        (vf->priv->x2 - vf->priv->x1)/2 );
			}
		}
	} else { // Blit the bitmap to the videoscreen, pixel for pixel
	    for( ypos=vf->priv->y1 ; ypos < vf->priv->y2 ; ypos++ ) {
	        for ( xpos=vf->priv->x1 ; xpos < vf->priv->x2 ; xpos++ ) {
				pos = (ypos * dmpi->stride[0]) + xpos;

				alpha = vf->priv->bitmap.a[pos];

				if (alpha == 0) continue; // Completly transparent pixel

				if (alpha == 255) {	// Opaque pixel
					dmpi->planes[0][pos] = vf->priv->bitmap.y[pos];
					if ((ypos%2) && (xpos%2)) {
						pos = ( (ypos/2) * dmpi->stride[1] ) + (xpos/2);
						dmpi->planes[1][pos] = vf->priv->bitmap.u[pos];
						dmpi->planes[2][pos] = vf->priv->bitmap.v[pos];
					}
				} else { // Alphablended pixel
					dmpi->planes[0][pos] =
						((255 - alpha) * (int)dmpi->planes[0][pos] +
						alpha * (int)vf->priv->bitmap.y[pos]) >> 8;

					if ((ypos%2) && (xpos%2)) {
						pos = ( (ypos/2) * dmpi->stride[1] ) + (xpos/2);

						dmpi->planes[1][pos] =
							((255 - alpha) * (int)dmpi->planes[1][pos] +
							alpha * (int)vf->priv->bitmap.u[pos]) >> 8;

						dmpi->planes[2][pos] =
							((255 - alpha) * (int)dmpi->planes[2][pos] +
							alpha * (int)vf->priv->bitmap.v[pos]) >> 8;
					}
			    }
			} // for xpos
		} // for ypos
	} // if !opaque
Exemple #16
0
static int demux_avs_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds)
{
    AVS_VideoFrame *curr_frame;
    demux_packet_t *dp = NULL;
    AVS_T *AVS = demuxer->priv;

    if (ds == demuxer->video)
    {
        sh_video_t *sh_video = demuxer->video->sh;
        char *dst;
        int w, h;
        if (AVS->video_info->num_frames <= AVS->frameno) return 0; // EOF

        curr_frame = AVS->avs_get_frame(AVS->clip, AVS->frameno);
        if (!curr_frame)
        {
            mp_msg(MSGT_DEMUX, MSGL_V, "AVS: error getting frame -- EOF??\n");
            return 0;
        }
        w = curr_frame->row_size;
        h = curr_frame->height;

        dp = new_demux_packet(w * h + 2 * (w / 2) * (h / 2));

        dp->pts=AVS->frameno / sh_video->fps;

        dst = dp->buffer;
        memcpy_pic(dst, curr_frame->vfb->data + curr_frame->offset,
                   w, h, w, curr_frame->pitch);
        dst += w * h;
        w /= 2; h /= 2;
        memcpy_pic(dst, curr_frame->vfb->data + curr_frame->offsetV,
                   w, h, w, curr_frame->pitchUV);
        dst += w * h;
        memcpy_pic(dst, curr_frame->vfb->data + curr_frame->offsetU,
                   w, h, w, curr_frame->pitchUV);
        ds_add_packet(demuxer->video, dp);

        AVS->frameno++;
        AVS->avs_release_video_frame(curr_frame);
    }

    /* Audio */
    if (ds == demuxer->audio)
    {
        sh_audio_t *sh_audio = ds->sh;
        int samples = sh_audio->samplerate;
        uint64_t l;
        samples = FFMIN(samples, AVS->video_info->num_audio_samples - AVS->sampleno);
        if (!samples) return 0;
        l = samples * sh_audio->channels * sh_audio->samplesize;
        if (l > INT_MAX) {
            mp_msg(MSGT_DEMUX, MSGL_FATAL, "AVS: audio packet too big\n");
            return 0;
        }
        dp = new_demux_packet(l);
        dp->pts = AVS->sampleno / sh_audio->samplerate;

        if (AVS->avs_get_audio(AVS->clip, dp->buffer, AVS->sampleno, samples))
        {
            mp_msg(MSGT_DEMUX, MSGL_V, "AVS: avs_get_audio() failed\n");
            return 0;
        }
        ds_add_packet(demuxer->audio, dp);

        AVS->sampleno += samples;
    }

    return 1;
}
Exemple #17
0
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
    mp_image_t *dmpi;
    int ret;
    int w            = (IMGFMT_IS_YUVP16(mpi->imgfmt) ? 2 : 1) * mpi->w;
    int chroma_width = (IMGFMT_IS_YUVP16(mpi->imgfmt) ? 2 : 1) * mpi->chroma_width;

    vf->priv->frame = (vf->priv->frame+1)%4;

    dmpi = vf_get_image(vf->next, mpi->imgfmt,
                        MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE |
                        MP_IMGFLAG_PRESERVE, mpi->width, mpi->height);

    ret = 0;
    //    0/0  1/1  2/2  2/3  3/0
    switch (vf->priv->frame) {
    case 0:
        my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
                      mpi->planes[0]+mpi->stride[0], w, mpi->h/2,
                      dmpi->stride[0]*2, mpi->stride[0]*2);
        if (mpi->flags & MP_IMGFLAG_PLANAR) {
            my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
                          mpi->planes[1]+mpi->stride[1],
                          chroma_width, mpi->chroma_height/2,
                          dmpi->stride[1]*2, mpi->stride[1]*2);
            my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
                          mpi->planes[2]+mpi->stride[2],
                          chroma_width, mpi->chroma_height/2,
                          dmpi->stride[2]*2, mpi->stride[2]*2);
        }
        ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
    /* Fallthrough */
    case 1:
    case 2:
        memcpy_pic(dmpi->planes[0], mpi->planes[0], w, mpi->h,
                   dmpi->stride[0], mpi->stride[0]);
        if (mpi->flags & MP_IMGFLAG_PLANAR) {
            memcpy_pic(dmpi->planes[1], mpi->planes[1],
                       chroma_width, mpi->chroma_height,
                       dmpi->stride[1], mpi->stride[1]);
            memcpy_pic(dmpi->planes[2], mpi->planes[2],
                       chroma_width, mpi->chroma_height,
                       dmpi->stride[2], mpi->stride[2]);
        }
        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE) || ret;
    case 3:
        my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0],
                      mpi->planes[0]+mpi->stride[0], w, mpi->h/2,
                      dmpi->stride[0]*2, mpi->stride[0]*2);
        if (mpi->flags & MP_IMGFLAG_PLANAR) {
            my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1],
                          mpi->planes[1]+mpi->stride[1],
                          chroma_width, mpi->chroma_height/2,
                          dmpi->stride[1]*2, mpi->stride[1]*2);
            my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2],
                          mpi->planes[2]+mpi->stride[2],
                          chroma_width, mpi->chroma_height/2,
                          dmpi->stride[2]*2, mpi->stride[2]*2);
        }
        ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
        my_memcpy_pic(dmpi->planes[0], mpi->planes[0], w, mpi->h/2,
                      dmpi->stride[0]*2, mpi->stride[0]*2);
        if (mpi->flags & MP_IMGFLAG_PLANAR) {
            my_memcpy_pic(dmpi->planes[1], mpi->planes[1],
                          chroma_width, mpi->chroma_height/2,
                          dmpi->stride[1]*2, mpi->stride[1]*2);
            my_memcpy_pic(dmpi->planes[2], mpi->planes[2],
                          chroma_width, mpi->chroma_height/2,
                          dmpi->stride[2]*2, mpi->stride[2]*2);
        }
        return ret;
    }
    return 0;
}
Exemple #18
0
Fichier : vo_xv.c Projet : kax4/mpv
static void draw_osd(struct vo *vo, struct osd_state *osd)
{
    struct xvctx *ctx = vo->priv;

    struct mp_image img = get_xv_buffer(vo, ctx->current_buf);

    struct mp_rect *src = &ctx->src_rect;
    struct mp_rect *dst = &ctx->dst_rect;
    int dw = dst->x1 - dst->x0, dh = dst->y1 - dst->y0;
    int sw = src->x1 - src->x0, sh = src->y1 - src->y0;
    double xvpar = (double)dw / dh * sh / sw;

    struct mp_osd_res res = {
        .w = ctx->image_width,
        .h = ctx->image_height,
        .display_par = vo->monitor_par / xvpar,
        .video_par = vo->aspdat.par,
    };

    osd_draw_on_image_bk(osd, res, osd->vo_pts, 0, ctx->osd_backup, &img);
}

static int redraw_frame(struct vo *vo)
{
    struct xvctx *ctx = vo->priv;

    struct mp_image img = get_xv_buffer(vo, ctx->visible_buf);
    mp_draw_sub_backup_restore(ctx->osd_backup, &img);
    ctx->current_buf = ctx->visible_buf;

    return true;
}

static void flip_page(struct vo *vo)
{
    struct xvctx *ctx = vo->priv;
    put_xvimage(vo, ctx->xvimage[ctx->current_buf]);

    /* remember the currently visible buffer */
    ctx->visible_buf = ctx->current_buf;

    ctx->current_buf = (ctx->current_buf + 1) % ctx->num_buffers;
    XFlush(vo->x11->display);
    return;
}

static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w,
                      int h, int x, int y)
{
    struct xvctx *ctx = vo->priv;
    uint8_t *dst;
    XvImage *current_image = ctx->xvimage[ctx->current_buf];

    dst = current_image->data + current_image->offsets[0]
        + current_image->pitches[0] * y + x;
    memcpy_pic(dst, image[0], w, h, current_image->pitches[0], stride[0]);

    x /= 2;
    y /= 2;
    w /= 2;
    h /= 2;

    dst = current_image->data + current_image->offsets[1]
        + current_image->pitches[1] * y + x;
    if (ctx->image_format != IMGFMT_YV12)
        memcpy_pic(dst, image[1], w, h, current_image->pitches[1], stride[1]);
    else
        memcpy_pic(dst, image[2], w, h, current_image->pitches[1], stride[2]);

    dst = current_image->data + current_image->offsets[2]
        + current_image->pitches[2] * y + x;
    if (ctx->image_format == IMGFMT_YV12)
        memcpy_pic(dst, image[1], w, h, current_image->pitches[1], stride[1]);
    else
        memcpy_pic(dst, image[2], w, h, current_image->pitches[1], stride[2]);

    mp_draw_sub_backup_reset(ctx->osd_backup);

    return 0;
}

static mp_image_t *get_screenshot(struct vo *vo)
{
    struct xvctx *ctx = vo->priv;

    struct mp_image img = get_xv_buffer(vo, ctx->visible_buf);
    struct mp_image *res = alloc_mpi(img.w, img.h, img.imgfmt);
    copy_mpi(res, &img);
    vf_clone_mpi_attributes(res, &img);
    // try to get an image without OSD
    mp_draw_sub_backup_restore(ctx->osd_backup, res);
    res->display_w = vo->aspdat.prew;
    res->display_h = vo->aspdat.preh;

    return res;
}

static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
{
    struct xvctx *ctx = vo->priv;

    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
        ; // done
    else if (mpi->flags & MP_IMGFLAG_PLANAR)
        draw_slice(vo, mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
    else if (mpi->flags & MP_IMGFLAG_YUV)
        // packed YUV:
        memcpy_pic(ctx->xvimage[ctx->current_buf]->data +
                   ctx->xvimage[ctx->current_buf]->offsets[0], mpi->planes[0],
                   mpi->w * (mpi->bpp / 8), mpi->h,
                   ctx->xvimage[ctx->current_buf]->pitches[0], mpi->stride[0]);
    else
          return false;

    mp_draw_sub_backup_reset(ctx->osd_backup);

    return true;
}

static int query_format(struct xvctx *ctx, uint32_t format)
{
    uint32_t i;
    int flag = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD | VFCAP_ACCEPT_STRIDE;       // FIXME! check for DOWN

    /* check image formats */
    for (i = 0; i < ctx->formats; i++) {
        if (ctx->fo[i].id == format)
            return flag;        //xv_format = fo[i].id;
    }
    return 0;
}
Exemple #19
0
static void delogo(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height,
                   int logo_x, int logo_y, int logo_w, int logo_h, int band, int show, int direct) {
    int y, x;
    int interp, dist;
    uint8_t *xdst, *xsrc;

    uint8_t *topleft, *botleft, *topright;
    int xclipl, xclipr, yclipt, yclipb;
    int logo_x1, logo_x2, logo_y1, logo_y2;

    xclipl = MAX(-logo_x, 0);
    xclipr = MAX(logo_x+logo_w-width, 0);
    yclipt = MAX(-logo_y, 0);
    yclipb = MAX(logo_y+logo_h-height, 0);

    logo_x1 = logo_x + xclipl;
    logo_x2 = logo_x + logo_w - xclipr;
    logo_y1 = logo_y + yclipt;
    logo_y2 = logo_y + logo_h - yclipb;

    topleft = src+logo_y1*srcStride+logo_x1;
    topright = src+logo_y1*srcStride+logo_x2-1;
    botleft = src+(logo_y2-1)*srcStride+logo_x1;

    if (!direct) memcpy_pic(dst, src, width, height, dstStride, srcStride);

    dst += (logo_y1+1)*dstStride;
    src += (logo_y1+1)*srcStride;

    for(y = logo_y1+1; y < logo_y2-1; y++)
    {
        for (x = logo_x1+1, xdst = dst+logo_x1+1, xsrc = src+logo_x1+1; x < logo_x2-1; x++, xdst++, xsrc++) {
            interp = ((topleft[srcStride*(y-logo_y-yclipt)]
                       + topleft[srcStride*(y-logo_y-1-yclipt)]
                       + topleft[srcStride*(y-logo_y+1-yclipt)])*(logo_w-(x-logo_x))/logo_w
                      + (topright[srcStride*(y-logo_y-yclipt)]
                         + topright[srcStride*(y-logo_y-1-yclipt)]
                         + topright[srcStride*(y-logo_y+1-yclipt)])*(x-logo_x)/logo_w
                      + (topleft[x-logo_x-xclipl]
                         + topleft[x-logo_x-1-xclipl]
                         + topleft[x-logo_x+1-xclipl])*(logo_h-(y-logo_y))/logo_h
                      + (botleft[x-logo_x-xclipl]
                         + botleft[x-logo_x-1-xclipl]
                         + botleft[x-logo_x+1-xclipl])*(y-logo_y)/logo_h
                     )/6;
            /*		interp = (topleft[srcStride*(y-logo_y)]*(logo_w-(x-logo_x))/logo_w
            			  + topright[srcStride*(y-logo_y)]*(x-logo_x)/logo_w
            			  + topleft[x-logo_x]*(logo_h-(y-logo_y))/logo_h
            			  + botleft[x-logo_x]*(y-logo_y)/logo_h
            			  )/2;*/
            if (y >= logo_y+band && y < logo_y+logo_h-band && x >= logo_x+band && x < logo_x+logo_w-band) {
                *xdst = interp;
            } else {
                dist = 0;
                if (x < logo_x+band) dist = MAX(dist, logo_x-x+band);
                else if (x >= logo_x+logo_w-band) dist = MAX(dist, x-(logo_x+logo_w-1-band));
                if (y < logo_y+band) dist = MAX(dist, logo_y-y+band);
                else if (y >= logo_y+logo_h-band) dist = MAX(dist, y-(logo_y+logo_h-1-band));
                *xdst = (*xsrc*dist + interp*(band-dist))/band;
                if (show && (dist == band-1)) *xdst = 0;
            }
        }

        dst+= dstStride;
        src+= srcStride;
    }
}
Exemple #20
0
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi)
{
	struct pullup_context *c = vf->priv->ctx;
	struct pullup_buffer *b;
	struct pullup_frame *f;
	int p;
	int i;
        double pts = mpi->pts;
        struct mp_image *dmpi = NULL;

	if (!vf->priv->init) init_pullup(vf, mpi);

	if (1) {
		b = pullup_get_buffer(c, 2);
		if (!b) {
			mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n");
			f = pullup_get_frame(c);
			pullup_release_frame(f);
			goto skip;
		}
		memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h,
			c->stride[0], mpi->stride[0]);
			memcpy_pic(b->planes[1], mpi->planes[1],
				mpi->chroma_width, mpi->chroma_height,
				c->stride[1], mpi->stride[1]);
			memcpy_pic(b->planes[2], mpi->planes[2],
				mpi->chroma_width, mpi->chroma_height,
				c->stride[2], mpi->stride[2]);
	}
	if (mpi->qscale) {
		memcpy(b->planes[3], mpi->qscale, c->w[3]);
		memcpy(b->planes[3]+c->w[3], mpi->qscale, c->w[3]);
	}

	p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 :
		(mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0);

	if (pts == MP_NOPTS_VALUE) {
		pullup_submit_field(c, b, p, MP_NOPTS_VALUE);
		pullup_submit_field(c, b, p^1, MP_NOPTS_VALUE);
		if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST)
			pullup_submit_field(c, b, p, MP_NOPTS_VALUE);
	} else {
		double delta;
		if (vf->priv->lastpts == MP_NOPTS_VALUE)
			delta = 1001.0/60000.0; // delta = field time distance
		else
			delta = (pts - vf->priv->lastpts) / 2;
		if (delta <= 0.0 || delta >= 0.5)
			delta = 0.0;
		vf->priv->lastpts = pts;
		if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) {
			pullup_submit_field(c, b, p, pts - delta);
			pullup_submit_field(c, b, p^1, pts);
			pullup_submit_field(c, b, p, pts + delta);
		} else {
			pullup_submit_field(c, b, p, pts - delta * 0.5);
			pullup_submit_field(c, b, p^1, pts + delta * 0.5);
		}
	}

	pullup_release_buffer(b, 2);

	f = pullup_get_frame(c);

	/* Fake yes for first few frames (buffer depth) to keep from
	 * breaking A/V sync with G1's bad architecture... */
	//if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0;
	if (!f)
            goto skip;

	if (f->length < 2) {
		pullup_release_frame(f);
		f = pullup_get_frame(c);
		if (!f) goto skip;
		if (f->length < 2) {
			pullup_release_frame(f);
			if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST))
				goto skip;
			f = pullup_get_frame(c);
			if (!f) goto skip;
			if (f->length < 2) {
				pullup_release_frame(f);
				goto skip;
			}
		}
	}

#if 0
	/* Average qscale tables from both frames. */
	if (mpi->qscale) {
		for (i=0; i<c->w[3]; i++) {
			vf->priv->qbuf[i] = (f->ofields[0]->planes[3][i]
				+ f->ofields[1]->planes[3][i+c->w[3]])>>1;
		}
	}
#else
	/* Take worst of qscale tables from both frames. */
	if (mpi->qscale) {
		for (i=0; i<c->w[3]; i++) {
			vf->priv->qbuf[i] = MAX(f->ofields[0]->planes[3][i], f->ofields[1]->planes[3][i+c->w[3]]);
		}
	}
#endif

        /* If the frame isn't already exportable... */
        if (!f->buffer)
            pullup_pack_frame(c, f);

        // NOTE: the copy could probably be avoided by changing or using the
        //       pullup internal buffer management. But right now just do the
        //       safe thing and always copy. Code outside the filter might
        //       hold a buffer reference even if the filter chain is destroyed.
        dmpi = vf_alloc_out_image(vf);
        mp_image_copy_attributes(dmpi, mpi);

        struct mp_image data = *dmpi;

	data.planes[0] = f->buffer->planes[0];
	data.planes[1] = f->buffer->planes[1];
	data.planes[2] = f->buffer->planes[2];

	data.stride[0] = c->stride[0];
	data.stride[1] = c->stride[1];
	data.stride[2] = c->stride[2];

        mp_image_copy(dmpi, &data);

        dmpi->pts = f->pts;

        // Warning: entirely bogus memory management of qscale
	if (mpi->qscale) {
		dmpi->qscale = vf->priv->qbuf;
		dmpi->qstride = mpi->qstride;
		dmpi->qscale_type = mpi->qscale_type;
	}
	pullup_release_frame(f);

skip:
        talloc_free(mpi);
	return dmpi;
}
Exemple #21
0
static void draw_image(struct vo *vo, mp_image_t *mpi)
{
    memcpy_pic(dither_buffer, mpi->planes[0], image_width * depth, image_height,
               image_width * depth, mpi->stride[0]);
    caca_dither_bitmap(canvas, 0, 0, screen_w, screen_h, dither, dither_buffer);
}
Exemple #22
0
/** @brief Render a frame on the screen.
 *  @param mpi mpi structure with the decoded frame inside
 *  @return VO_TRUE on success, VO_ERROR on failure
 */
static uint32_t render_d3d_frame(mp_image_t *mpi)
{
    /* Uncomment when direct rendering is implemented.
     * if (mpi->flags & MP_IMGFLAG_DIRECT) ...
     */

    /* If the D3D device is uncooperative (not initialized), return success.
       The device will be probed for reinitialization in the next flip_page() */
    if (!priv->d3d_device)
        return VO_TRUE;

    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
        goto skip_upload;

    if (mpi->flags & MP_IMGFLAG_PLANAR) { /* Copy a planar frame. */
        draw_slice(mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
        goto skip_upload;
    }

    /* If we're here, then we should lock the rect and copy a packed frame */
    if (!priv->locked_rect.pBits) {
        if (FAILED(IDirect3DSurface9_LockRect(priv->d3d_surface,
                                              &priv->locked_rect, NULL, 0))) {
            mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Surface lock failed.\n");
            return VO_ERROR;
        }
    }

    memcpy_pic(priv->locked_rect.pBits, mpi->planes[0], mpi->stride[0],
               mpi->height, priv->locked_rect.Pitch, mpi->stride[0]);

skip_upload:
    /* This unlock is used for both slice_draw path and render_d3d_frame path. */
    if (FAILED(IDirect3DSurface9_UnlockRect(priv->d3d_surface))) {
        mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Surface unlock failed.\n");
        return VO_ERROR;
    }
    priv->locked_rect.pBits = NULL;

    if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>BeginScene failed.\n");
        return VO_ERROR;
    }

    if (priv->is_clear_needed) {
        IDirect3DDevice9_Clear(priv->d3d_device, 0, NULL,
                               D3DCLEAR_TARGET, 0, 0, 0);
        priv->is_clear_needed = 0;
    }

    if (FAILED(IDirect3DDevice9_StretchRect(priv->d3d_device,
                                            priv->d3d_surface,
                                            &priv->fs_panscan_rect,
                                            priv->d3d_backbuf,
                                            &priv->fs_movie_rect,
                                            D3DTEXF_LINEAR))) {
        mp_msg(MSGT_VO, MSGL_ERR,
               "<vo_direct3d>Copying frame to the backbuffer failed.\n");
        return VO_ERROR;
    }

    if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) {
        mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>EndScene failed.\n");
        return VO_ERROR;
    }

    return VO_TRUE;
}
Exemple #23
0
static int
IvtcFilter (VideoFilter *vf, VideoFrame *frame, int field)
{
    (void)field;
    ThisFilter *filter = (ThisFilter *) vf;

    if (!frame->interlaced_frame)
    {
        filter->progressive_frame_seen = 1;
    }

    if (filter->progressive_frame_seen &&
        frame->interlaced_frame)
    {
        filter->interlaced_frame_seen = 1;
    }

    if (!frame->interlaced_frame &&
        !filter->apply_filter &&
        filter->interlaced_frame_seen &&
        filter->progressive_frame_seen)
    {
        fprintf(stderr,"turning on inverse telecine filter");
        filter->apply_filter = 1;
    }

    if (!filter->apply_filter)
        return 1;

    SetupFilter(filter, frame->width, frame->height, (int*)frame->pitches);

    struct pullup_buffer *b;
    struct pullup_frame *f;
    int ypitch  = filter->context->stride[0];
    int height  = filter->height;
    int cpitch  = filter->context->stride[1];
    int cheight = filter->height >> 1;
    int p = frame->top_field_first ^ 1;

    struct pullup_context *c = filter->context;
    if (c->bpp[0] == 0)
        c->bpp[0] = c->bpp[1] = c->bpp[2] = frame->bpp;

    b = pullup_get_buffer(c,2);
    if (!b)
    {
        f = pullup_get_frame(c);
        pullup_release_frame(f);
        return 0;
    }

    memcpy_pic(b->planes[0], frame->buf + frame->offsets[0],
               height,  ypitch, ypitch);
    memcpy_pic(b->planes[1], frame->buf + frame->offsets[1],
               cheight, cpitch, cpitch);
    memcpy_pic(b->planes[2], frame->buf + frame->offsets[2],
               cheight, cpitch, cpitch);

    pullup_submit_field(c, b, p);
    pullup_submit_field(c, b, p^1);
    if (frame->repeat_pict)
        pullup_submit_field(c, b, p);

    pullup_release_buffer(b, 2);

    f = pullup_get_frame(c);

    if (!f)
        return 0;


    if (f->length < 2)
    {
        pullup_release_frame(f);
        f = pullup_get_frame(c);
        if (!f)
            return 0;
        if (f->length < 2)
        {
            pullup_release_frame(f);
            if (!frame->repeat_pict)
                return 0;
            f = pullup_get_frame(c);
            if (!f)
                return 0;
            if (f->length < 2)
            {
                pullup_release_frame(f);
                return 0;
            }
        }
    }

    if (!f->buffer)
    {
        pullup_pack_frame(c, f);
    }

    if (!f->buffer)
        return 0;

    memcpy_pic(frame->buf + frame->offsets[0], f->buffer->planes[0],
               height,  ypitch, ypitch);
    memcpy_pic(frame->buf + frame->offsets[1], f->buffer->planes[1],
               cheight, cpitch, cpitch);
    memcpy_pic(frame->buf + frame->offsets[2], f->buffer->planes[2],
               cheight, cpitch, cpitch);

    pullup_release_frame(f);

    return 1;
}
Exemple #24
0
/**
 * @brief Read and decode a PNG file into bitmap data.
 *
 * @param fname filename (with path)
 * @param img pointer suitable to store the image data
 *
 * @return 0 (ok), 1 (decoding error), 2 (open error), 3 (file too big),
 *                 4 (out of memory), 5 (avcodec alloc error)
 */
static int pngRead(const char *fname, guiImage *img)
{
    FILE *file;
    long len;
    void *data;
    int decode_ok, bpl;
    AVCodecContext *avctx;
    AVFrame *frame;
    AVPacket pkt;

    file = fopen(fname, "rb");

    if (!file)
        return 2;

    fseek(file, 0, SEEK_END);
    len = ftell(file);

    if (len > 50 * 1024 * 1024 || len < 8) {
        fclose(file);
        return 3;
    }

    data = av_malloc(len + FF_INPUT_BUFFER_PADDING_SIZE);

    if (!data) {
        fclose(file);
        return 4;
    }

    fseek(file, 0, SEEK_SET);
    fread(data, len, 1, file);
    fclose(file);

    avctx = avcodec_alloc_context3(NULL);
    frame = av_frame_alloc();

    if (!(avctx && frame)) {
        av_free(frame);
        av_free(avctx);
        av_free(data);
        return 5;
    }

    avcodec_register_all();
    avcodec_open2(avctx, avcodec_find_decoder(AV_CODEC_ID_PNG), NULL);

    av_init_packet(&pkt);
    pkt.data = data;
    pkt.size = len;
    // HACK: make PNGs decode normally instead of as CorePNG delta frames
    pkt.flags = AV_PKT_FLAG_KEY;
    avcodec_decode_video2(avctx, frame, &decode_ok, &pkt);
    memset(img, 0, sizeof(*img));

    switch (avctx->pix_fmt) {
    case AV_PIX_FMT_GRAY8:
        img->Bpp = 8;
        break;

    case AV_PIX_FMT_GRAY16BE:
        img->Bpp = 16;
        break;

    case AV_PIX_FMT_RGB24:
        img->Bpp = 24;
        break;

    case AV_PIX_FMT_RGBA:
        img->Bpp = 32;
        break;

    default:
        img->Bpp = 0;
        break;
    }

    if (decode_ok && img->Bpp) {
        img->Width  = avctx->width;
        img->Height = avctx->height;
        bpl = img->Width * (img->Bpp / 8);
        img->ImageSize = bpl * img->Height;

        mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[bitmap] file: %s\n", fname);
        mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[bitmap]  size: %lux%lu, color depth: %u\n", img->Width, img->Height, img->Bpp);
        mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[bitmap]  image size: %lu\n", img->ImageSize);

        img->Image = malloc(img->ImageSize);

        if (img->Image)
            memcpy_pic(img->Image, frame->data[0], bpl, img->Height, bpl, frame->linesize[0]);
        else
            decode_ok = 0;
    }

    avcodec_close(avctx);
    av_free(frame);
    av_free(avctx);
    av_free(data);

    return !(decode_ok && img->Bpp);
}
Exemple #25
0
static void modeset_destroy_fb(int fd, struct modeset_buf *buf)
{
    if (buf->map) {
        munmap(buf->map, buf->size);
    }
    if (buf->fb) {
        drmModeRmFB(fd, buf->fb);
    }
    if (buf->handle) {
        struct drm_mode_destroy_dumb dreq = {
            .handle = buf->handle,
        };
        drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
    }
}

static int modeset_create_fb(struct vo *vo, int fd, struct modeset_buf *buf)
{
    int ret = 0;

    buf->handle = 0;

    // create dumb buffer
    struct drm_mode_create_dumb creq = {
        .width = buf->width,
        .height = buf->height,
        .bpp = 32,
    };
    ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
    if (ret < 0) {
        MP_ERR(vo, "Cannot create dumb buffer: %s\n", mp_strerror(errno));
        ret = -errno;
        goto end;
    }
    buf->stride = creq.pitch;
    buf->size = creq.size;
    buf->handle = creq.handle;

    // create framebuffer object for the dumb-buffer
    ret = drmModeAddFB(fd, buf->width, buf->height, 24, 32, buf->stride,
                       buf->handle, &buf->fb);
    if (ret) {
        MP_ERR(vo, "Cannot create framebuffer: %s\n", mp_strerror(errno));
        ret = -errno;
        goto end;
    }

    // prepare buffer for memory mapping
    struct drm_mode_map_dumb mreq = {
        .handle = buf->handle,
    };
    ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
    if (ret) {
        MP_ERR(vo, "Cannot map dumb buffer: %s\n", mp_strerror(errno));
        ret = -errno;
        goto end;
    }

    // perform actual memory mapping
    buf->map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
                    fd, mreq.offset);
    if (buf->map == MAP_FAILED) {
        MP_ERR(vo, "Cannot map dumb buffer: %s\n", mp_strerror(errno));
        ret = -errno;
        goto end;
    }

    memset(buf->map, 0, buf->size);

end:
    if (ret == 0) {
        return 0;
    }

    modeset_destroy_fb(fd, buf);
    return ret;
}

static int modeset_find_crtc(struct vo *vo, int fd, drmModeRes *res,
                             drmModeConnector *conn, struct modeset_dev *dev)
{
    for (unsigned int i = 0; i < conn->count_encoders; ++i) {
        drmModeEncoder *enc = drmModeGetEncoder(fd, conn->encoders[i]);
        if (!enc) {
            MP_WARN(vo, "Cannot retrieve encoder %u:%u: %s\n",
                    i, conn->encoders[i], mp_strerror(errno));
            continue;
        }

        // iterate all global CRTCs
        for (unsigned int j = 0; j < res->count_crtcs; ++j) {
            // check whether this CRTC works with the encoder
            if (!(enc->possible_crtcs & (1 << j)))
                continue;

            dev->enc = enc;
            dev->crtc = enc->crtc_id;
            return 0;
        }

        drmModeFreeEncoder(enc);
    }

    MP_ERR(vo, "Connector %u has no suitable CRTC\n", conn->connector_id);
    return -ENOENT;
}

static bool is_connector_valid(struct vo *vo, int conn_id,
                               drmModeConnector *conn, bool silent)
{
    if (!conn) {
        if (!silent) {
            MP_ERR(vo, "Cannot get connector %d: %s\n", conn_id,
                   mp_strerror(errno));
        }
        return false;
    }

    if (conn->connection != DRM_MODE_CONNECTED) {
        if (!silent) {
            MP_ERR(vo, "Connector %d is disconnected\n", conn_id);
        }
        return false;
    }

    if (conn->count_modes == 0) {
        if (!silent) {
            MP_ERR(vo, "Connector %d has no valid modes\n", conn_id);
        }
        return false;
    }

    return true;
}

static int modeset_prepare_dev(struct vo *vo, int fd, int conn_id,
                               struct modeset_dev **out)
{
    struct modeset_dev *dev = NULL;
    drmModeConnector *conn = NULL;

    int ret = 0;
    *out = NULL;

    drmModeRes *res = drmModeGetResources(fd);
    if (!res) {
        MP_ERR(vo, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
        ret = -errno;
        goto end;
    }

    if (conn_id == -1) {
        // get the first connected connector
        for (int i = 0; i < res->count_connectors; i++) {
            conn = drmModeGetConnector(fd, res->connectors[i]);
            if (is_connector_valid(vo, i, conn, true)) {
                conn_id = i;
                break;
            }
            if (conn) {
                drmModeFreeConnector(conn);
                conn = NULL;
            }
        }
        if (conn_id == -1) {
            MP_ERR(vo, "No connected connectors found\n");
            ret = -ENODEV;
            goto end;
        }
    }

    if (conn_id < 0 || conn_id >= res->count_connectors) {
        MP_ERR(vo, "Bad connector ID. Max valid connector ID = %u\n",
               res->count_connectors);
        ret = -ENODEV;
        goto end;
    }

    conn = drmModeGetConnector(fd, res->connectors[conn_id]);
    if (!is_connector_valid(vo, conn_id, conn, false)) {
        ret = -ENODEV;
        goto end;
    }

    dev = talloc_zero(vo->priv, struct modeset_dev);
    dev->conn = conn->connector_id;
    dev->front_buf = 0;
    dev->mode = conn->modes[0];
    dev->bufs[0].width = conn->modes[0].hdisplay;
    dev->bufs[0].height = conn->modes[0].vdisplay;
    dev->bufs[1].width = conn->modes[0].hdisplay;
    dev->bufs[1].height = conn->modes[0].vdisplay;

    MP_INFO(vo, "Connector using mode %ux%u\n",
            dev->bufs[0].width, dev->bufs[0].height);

    ret = modeset_find_crtc(vo, fd, res, conn, dev);
    if (ret) {
        MP_ERR(vo, "Connector %d has no valid CRTC\n", conn_id);
        goto end;
    }

    for (unsigned int i = 0; i < BUF_COUNT; i++) {
        ret = modeset_create_fb(vo, fd, &dev->bufs[i]);
        if (ret) {
            MP_ERR(vo, "Cannot create framebuffer for connector %d\n",
                   conn_id);
            for (unsigned int j = 0; j < i; j++) {
                modeset_destroy_fb(fd, &dev->bufs[j]);
            }
            goto end;
        }
    }

end:
    if (conn) {
        drmModeFreeConnector(conn);
        conn = NULL;
    }
    if (res) {
        drmModeFreeResources(res);
        res = NULL;
    }
    if (ret == 0) {
        *out = dev;
    } else {
        talloc_free(dev);
    }
    return ret;
}

static void modeset_page_flipped(int fd, unsigned int frame, unsigned int sec,
                                 unsigned int usec, void *data)
{
    struct priv *p = data;
    p->pflip_happening = false;
}



static int setup_vo_crtc(struct vo *vo)
{
    struct priv *p = vo->priv;
    if (p->active)
        return 0;
    p->old_crtc = drmModeGetCrtc(p->fd, p->dev->crtc);
    int ret = drmModeSetCrtc(p->fd, p->dev->crtc,
                          p->dev->bufs[p->dev->front_buf + BUF_COUNT - 1].fb,
                          0, 0, &p->dev->conn, 1, &p->dev->mode);
    p->active = true;
    return ret;
}

static void release_vo_crtc(struct vo *vo)
{
    struct priv *p = vo->priv;

    if (!p->active)
        return;
    p->active = false;

    // wait for current page flip
    while (p->pflip_happening) {
        int ret = drmHandleEvent(p->fd, &p->ev);
        if (ret) {
            MP_ERR(vo, "drmHandleEvent failed: %i\n", ret);
            break;
        }
    }

    if (p->old_crtc) {
        drmModeSetCrtc(p->fd,
                       p->old_crtc->crtc_id,
                       p->old_crtc->buffer_id,
                       p->old_crtc->x,
                       p->old_crtc->y,
                       &p->dev->conn,
                       1,
                       &p->dev->mode);
        drmModeFreeCrtc(p->old_crtc);
        p->old_crtc = NULL;
    }
}

static void release_vt(void *data)
{
    struct vo *vo = data;
    release_vo_crtc(vo);
    if (USE_MASTER) {
        //this function enables support for switching to x, weston etc.
        //however, for whatever reason, it can be called only by root users.
        //until things change, this is commented.
        struct priv *p = vo->priv;
        if (drmDropMaster(p->fd)) {
            MP_WARN(vo, "Failed to drop DRM master: %s\n", mp_strerror(errno));
        }
    }
}

static void acquire_vt(void *data)
{
    struct vo *vo = data;
    if (USE_MASTER) {
        struct priv *p = vo->priv;
        if (drmSetMaster(p->fd)) {
            MP_WARN(vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno));
        }
    }

    setup_vo_crtc(vo);
}



static int wait_events(struct vo *vo, int64_t until_time_us)
{
    struct priv *p = vo->priv;
    int64_t wait_us = until_time_us - mp_time_us();
    int timeout_ms = MPCLAMP((wait_us + 500) / 1000, 0, 10000);
    vt_switcher_poll(&p->vt_switcher, timeout_ms);
    return 0;
}

static void wakeup(struct vo *vo)
{
    struct priv *p = vo->priv;
    vt_switcher_interrupt_poll(&p->vt_switcher);
}

static int reconfig(struct vo *vo, struct mp_image_params *params, int flags)
{
    struct priv *p = vo->priv;

    vo->dwidth = p->device_w;
    vo->dheight = p->device_h;
    vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd);

    int32_t w = p->dst.x1 - p->dst.x0;
    int32_t h = p->dst.y1 - p->dst.y0;

    // p->osd contains the parameters assuming OSD rendering in window
    // coordinates, but OSD can only be rendered in the intersection
    // between window and video rectangle (i.e. not into panscan borders).
    p->osd.w = w;
    p->osd.h = h;
    p->osd.mt = MPMIN(0, p->osd.mt);
    p->osd.mb = MPMIN(0, p->osd.mb);
    p->osd.mr = MPMIN(0, p->osd.mr);
    p->osd.ml = MPMIN(0, p->osd.ml);

    p->x = (p->device_w - w) >> 1;
    p->y = (p->device_h - h) >> 1;

    mp_sws_set_from_cmdline(p->sws, vo->opts->sws_opts);
    p->sws->src = *params;
    p->sws->dst = (struct mp_image_params) {
        .imgfmt = IMGFMT_BGR0,
        .w = w,
        .h = h,
        .d_w = w,
        .d_h = h,
    };

    talloc_free(p->cur_frame);
    p->cur_frame = mp_image_alloc(IMGFMT_BGR0, p->device_w, p->device_h);
    mp_image_params_guess_csp(&p->sws->dst);
    mp_image_set_params(p->cur_frame, &p->sws->dst);

    struct modeset_buf *buf = p->dev->bufs;
    memset(buf[0].map, 0, buf[0].size);
    memset(buf[1].map, 0, buf[1].size);

    if (mp_sws_reinit(p->sws) < 0)
        return -1;

    vo->want_redraw = true;
    return 0;
}

static void draw_image(struct vo *vo, mp_image_t *mpi)
{
    struct priv *p = vo->priv;

    if (p->active) {
        struct mp_image src = *mpi;
        struct mp_rect src_rc = p->src;
        src_rc.x0 = MP_ALIGN_DOWN(src_rc.x0, mpi->fmt.align_x);
        src_rc.y0 = MP_ALIGN_DOWN(src_rc.y0, mpi->fmt.align_y);
        mp_image_crop_rc(&src, src_rc);
        mp_sws_scale(p->sws, p->cur_frame, &src);
        osd_draw_on_image(vo->osd, p->osd, src.pts, 0, p->cur_frame);

        struct modeset_buf *front_buf = &p->dev->bufs[p->dev->front_buf];
        int32_t shift = (p->device_w * p->y + p->x) * 4;
        memcpy_pic(front_buf->map + shift,
                   p->cur_frame->planes[0],
                   (p->dst.x1 - p->dst.x0) * 4,
                   p->dst.y1 - p->dst.y0,
                   p->device_w * 4,
                   p->cur_frame->stride[0]);
    }

    if (mpi != p->last_input) {
        talloc_free(p->last_input);
        p->last_input = mpi;
    }
}

static void flip_page(struct vo *vo)
{
    struct priv *p = vo->priv;
    if (!p->active || p->pflip_happening)
        return;

    int ret = drmModePageFlip(p->fd, p->dev->crtc,
                              p->dev->bufs[p->dev->front_buf].fb,
                              DRM_MODE_PAGE_FLIP_EVENT, p);
    if (ret) {
        MP_WARN(vo, "Cannot flip page for connector\n");
    } else {
        p->dev->front_buf++;
        p->dev->front_buf %= BUF_COUNT;
        p->pflip_happening = true;
    }

    // poll page flip finish event
    const int timeout_ms = 3000;
    struct pollfd fds[1] = {
        { .events = POLLIN, .fd = p->fd },
    };
    poll(fds, 1, timeout_ms);
    if (fds[0].revents & POLLIN) {
        ret = drmHandleEvent(p->fd, &p->ev);
        if (ret != 0) {
            MP_ERR(vo, "drmHandleEvent failed: %i\n", ret);
            return;
        }
    }
}

static void uninit(struct vo *vo)
{
    struct priv *p = vo->priv;

    if (p->dev) {
        release_vo_crtc(vo);

        modeset_destroy_fb(p->fd, &p->dev->bufs[1]);
        modeset_destroy_fb(p->fd, &p->dev->bufs[0]);
        drmModeFreeEncoder(p->dev->enc);
    }

    vt_switcher_destroy(&p->vt_switcher);
    talloc_free(p->last_input);
    talloc_free(p->cur_frame);
    talloc_free(p->dev);
    close(p->fd);
}

static int preinit(struct vo *vo)
{
    struct priv *p = vo->priv;
    p->sws = mp_sws_alloc(vo);
    p->fd = -1;
    p->ev.version = DRM_EVENT_CONTEXT_VERSION;
    p->ev.page_flip_handler = modeset_page_flipped;

    if (vt_switcher_init(&p->vt_switcher, vo->log))
        goto err;

    vt_switcher_acquire(&p->vt_switcher, acquire_vt, vo);
    vt_switcher_release(&p->vt_switcher, release_vt, vo);

    if (modeset_open(vo, &p->fd, p->device_path))
        goto err;

    if (modeset_prepare_dev(vo, p->fd, p->connector_id, &p->dev))
        goto err;

    assert(p->dev);
    p->device_w = p->dev->bufs[0].width;
    p->device_h = p->dev->bufs[0].height;

    if (setup_vo_crtc(vo)) {
        MP_ERR(vo, "Cannot set CRTC for connector %u: %s\n", p->connector_id,
               mp_strerror(errno));
        goto err;
    }

    return 0;

err:
    uninit(vo);
    return -1;
}

static int query_format(struct vo *vo, int format)
{
    return sws_isSupportedInput(imgfmt2pixfmt(format));
}

static int control(struct vo *vo, uint32_t request, void *data)
{
    struct priv *p = vo->priv;
    switch (request) {
    case VOCTRL_SCREENSHOT_WIN:
        *(struct mp_image**)data = mp_image_new_copy(p->cur_frame);
        return VO_TRUE;
    case VOCTRL_REDRAW_FRAME:
        draw_image(vo, p->last_input);
        return VO_TRUE;
    case VOCTRL_GET_PANSCAN:
        return VO_TRUE;
    case VOCTRL_SET_PANSCAN:
        if (vo->config_ok)
            reconfig(vo, vo->params, 0);
        return VO_TRUE;
    }
    return VO_NOTIMPL;
}

#define OPT_BASE_STRUCT struct priv

const struct vo_driver video_out_drm = {
    .name = "drm",
    .description = "Direct Rendering Manager",
    .preinit = preinit,
    .query_format = query_format,
    .reconfig = reconfig,
    .control = control,
    .draw_image = draw_image,
    .flip_page = flip_page,
    .uninit = uninit,
    .wait_events = wait_events,
    .wakeup = wakeup,
    .priv_size = sizeof(struct priv),
    .options = (const struct m_option[]) {
        OPT_STRING("devpath", device_path, 0),
        OPT_INT("connector", connector_id, 0),
        {0},
    },
    .priv_defaults = &(const struct priv) {