Пример #1
0
PUBLIC
Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette)
{
    XvMCSubpicturePrivate *subpicture_priv;
    XvMCContextPrivate *context_priv;
    struct pipe_context *pipe;
    struct pipe_box dst_box = {0, 0, 0, 0, 1, 1};

    assert(dpy);
    assert(palette);

    if (!subpicture)
        return XvMCBadSubpicture;

    subpicture_priv = subpicture->privData;
    context_priv = subpicture_priv->context->privData;
    pipe = context_priv->pipe;

    dst_box.width = subpicture->num_palette_entries;

    upload_sampler(pipe, subpicture_priv->palette, &dst_box, palette, 0, 0, 0);

    XVMC_MSG(XVMC_TRACE, "[XvMC] Palette of Subpicture %p set.\n", subpicture);

    return Success;
}
Пример #2
0
static int PipeToComponentOrder(enum pipe_format format, char *component_order)
{
   assert(component_order);

   switch (format) {
      case PIPE_FORMAT_B8G8R8X8_UNORM:
         return 0;

      case PIPE_FORMAT_R4A4_UNORM:
      case PIPE_FORMAT_A4R4_UNORM:
         component_order[0] = 'Y';
         component_order[1] = 'U';
         component_order[2] = 'V';
         component_order[3] = 'A';
         return 4;

      default:
         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format);
         component_order[0] = 0;
         component_order[1] = 0;
         component_order[2] = 0;
         component_order[3] = 0;
         return 0;
   }
}
Пример #3
0
PUBLIC
Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value)
{
    XvMCContextPrivate *context_priv;
    const char *attr;

    assert(dpy);

    if (!context || !context->privData)
        return XvMCBadContext;

    context_priv = context->privData;

    attr = XGetAtomName(dpy, attribute);
    if (!attr)
        return XvMCBadContext;

    if (strcmp(attr, XV_BRIGHTNESS))
        *value = context_priv->procamp.brightness * 1000;
    else if (strcmp(attr, XV_CONTRAST))
        *value = context_priv->procamp.contrast * 1000 - 1000;
    else if (strcmp(attr, XV_SATURATION))
        *value = context_priv->procamp.saturation * 1000 + 1000;
    else if (strcmp(attr, XV_HUE))
        *value = context_priv->procamp.hue * 1000;
    else if (strcmp(attr, XV_COLORSPACE))
        *value = context_priv->color_standard == VL_CSC_COLOR_STANDARD_BT_709;
    else
        return BadName;

    XVMC_MSG(XVMC_TRACE, "[XvMC] Got value %d for attribute %s.\n", *value, attr);

    return Success;
}
Пример #4
0
PUBLIC
Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
{
   XvMCSubpicturePrivate *subpicture_priv;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture);

   assert(dpy);

   if (!subpicture)
      return XvMCBadSubpicture;

   subpicture_priv = subpicture->privData;
   pipe_sampler_view_reference(&subpicture_priv->sampler, NULL);
   pipe_sampler_view_reference(&subpicture_priv->palette, NULL);
   FREE(subpicture_priv);

   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture);

   return Success;
}
Пример #5
0
PUBLIC
Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
{
   assert(dpy);

   if (!surface)
      return XvMCBadSurface;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Syncing surface %p\n", surface);

   return Success;
}
Пример #6
0
PUBLIC
Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image,
                               short srcx, short srcy, unsigned short width, unsigned short height,
                               short dstx, short dsty)
{
   XvMCSubpicturePrivate *subpicture_priv;
   XvMCContextPrivate *context_priv;
   struct pipe_context *pipe;
   struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1};
   unsigned src_stride;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture);

   assert(dpy);

   if (!subpicture)
      return XvMCBadSubpicture;

   assert(image);

   if (subpicture->xvimage_id != image->id)
      return BadMatch;

   /* No planar support for now */
   if (image->num_planes != 1)
      return BadMatch;

   subpicture_priv = subpicture->privData;
   context_priv = subpicture_priv->context->privData;
   pipe = context_priv->pipe;

   /* clipping should be done by upload_sampler and regardles what the documentation
   says image->pitches[0] doesn't seems to be in bytes, so don't use it */
   src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format);
   upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy);

   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture);

   return Success;
}
Пример #7
0
static unsigned NumPaletteEntries4XvID(int xvimage_id)
{
   switch (xvimage_id) {
      case FOURCC_RGB:
         return 0;

      case FOURCC_AI44:
      case FOURCC_IA44:
         return 16;

      default:
         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
         return 0;
   }
}
Пример #8
0
PUBLIC
Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
{
   assert(dpy);

   if (!surface)
      return XvMCBadSurface;

   // don't call flush here, because this is usually
   // called once for every slice instead of every frame

   XVMC_MSG(XVMC_TRACE, "[XvMC] Flushing surface %p\n", surface);

   return Success;
}
Пример #9
0
static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)
{
   switch (xvmc_format) {
      case XVMC_CHROMA_FORMAT_420:
         return PIPE_VIDEO_CHROMA_FORMAT_420;
      case XVMC_CHROMA_FORMAT_422:
         return PIPE_VIDEO_CHROMA_FORMAT_422;
      case XVMC_CHROMA_FORMAT_444:
         return PIPE_VIDEO_CHROMA_FORMAT_444;
      default:
         assert(0);
   }

   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format);

   return -1;
}
Пример #10
0
static enum pipe_format XvIDToPipe(int xvimage_id)
{
   switch (xvimage_id) {
      case FOURCC_RGB:
         return PIPE_FORMAT_B8G8R8X8_UNORM;

      case FOURCC_AI44:
         return PIPE_FORMAT_R4A4_UNORM;

      case FOURCC_IA44:
         return PIPE_FORMAT_A4R4_UNORM;

      default:
         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
         return PIPE_FORMAT_NONE;
   }
}
Пример #11
0
static enum pipe_video_profile ProfileToPipe(int xvmc_profile)
{
   if (xvmc_profile & XVMC_MPEG_1)
      assert(0);
   if (xvmc_profile & XVMC_MPEG_2)
      return PIPE_VIDEO_PROFILE_MPEG2_MAIN;
   if (xvmc_profile & XVMC_H263)
      assert(0);
   if (xvmc_profile & XVMC_MPEG_4)
      assert(0);

   assert(0);

   XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile);

   return -1;
}
Пример #12
0
PUBLIC
Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value)
{
   XvMCContextPrivate *context_priv;
   const char *attr;
   vl_csc_matrix csc;

   assert(dpy);

   if (!context || !context->privData)
      return XvMCBadContext;

   context_priv = context->privData;

   attr = XGetAtomName(dpy, attribute);
   if (!attr)
      return XvMCBadContext;

   if (strcmp(attr, XV_BRIGHTNESS))
      context_priv->procamp.brightness = value / 1000.0f;
   else if (strcmp(attr, XV_CONTRAST))
      context_priv->procamp.contrast = value / 1000.0f + 1.0f;
   else if (strcmp(attr, XV_SATURATION))
      context_priv->procamp.saturation = value / 1000.0f + 1.0f;
   else if (strcmp(attr, XV_HUE))
      context_priv->procamp.hue = value / 1000.0f;
   else if (strcmp(attr, XV_COLORSPACE))
      context_priv->color_standard = value ?
         VL_CSC_COLOR_STANDARD_BT_601 :
         VL_CSC_COLOR_STANDARD_BT_709;
   else
      return BadName;

   vl_csc_get_matrix
   (
      context_priv->color_standard,
      &context_priv->procamp, true, &csc
   );
   vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc);

   XVMC_MSG(XVMC_TRACE, "[XvMC] Set attribute %s to value %d.\n", attr, value);

   return Success;
}
Пример #13
0
PUBLIC
XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number)
{
   XvAttribute *result;

   assert(dpy && number);

   if (!context || !context->privData)
      return NULL;

   result = malloc(sizeof(attributes));
   if (!result)
      return NULL;

   memcpy(result, attributes, sizeof(attributes));
   *number = sizeof(attributes) / sizeof(XvAttribute);

   XVMC_MSG(XVMC_TRACE, "[XvMC] Returning %d attributes for context %p.\n", *number, context);

   return result;
}
Пример #14
0
PUBLIC
Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture,
                           short subx, short suby, unsigned short subw, unsigned short subh,
                           short surfx, short surfy, unsigned short surfw, unsigned short surfh)
{
   struct u_rect src_rect = {subx, subx + subw, suby, suby + subh};
   struct u_rect dst_rect = {surfx, surfx + surfw, surfy, surfy + surfh};

   XvMCSurfacePrivate *surface_priv;
   XvMCSubpicturePrivate *subpicture_priv;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface);

   assert(dpy);

   if (!target_surface)
      return XvMCBadSurface;

   if (!subpicture)
      return XvMCBadSubpicture;

   if (target_surface->context_id != subpicture->context_id)
      return BadMatch;

   /* TODO: Verify against subpicture independent scaling */

   surface_priv = target_surface->privData;
   subpicture_priv = subpicture->privData;

   /* TODO: Assert rects are within bounds? Or clip? */
   subpicture_priv->src_rect = src_rect;
   subpicture_priv->dst_rect = dst_rect;

   surface_priv->subpicture = subpicture;
   subpicture_priv->surface = target_surface;

   return Success;
}
Пример #15
0
PUBLIC
Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
                      short srcx, short srcy, unsigned short srcw, unsigned short srch,
                      short destx, short desty, unsigned short destw, unsigned short desth,
                      int flags)
{
   static int dump_window = -1;

   struct pipe_context *pipe;
   struct vl_compositor *compositor;
   struct vl_compositor_state *cstate;
   struct vl_screen *vscreen;

   XvMCSurfacePrivate *surface_priv;
   XvMCContextPrivate *context_priv;
   XvMCSubpicturePrivate *subpicture_priv;
   XvMCContext *context;
   struct u_rect src_rect = {srcx, srcx + srcw, srcy, srcy + srch};
   struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth};

   struct pipe_resource *tex;
   struct pipe_surface surf_templ, *surf;
   struct u_rect *dirty_area;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface);

   assert(dpy);

   if (!surface || !surface->privData)
      return XvMCBadSurface;

   surface_priv = surface->privData;
   context = surface_priv->context;
   context_priv = context->privData;

   assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
   assert(srcx + srcw - 1 < surface->width);
   assert(srcy + srch - 1 < surface->height);

   subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL;
   pipe = context_priv->pipe;
   compositor = &context_priv->compositor;
   cstate = &context_priv->cstate;
   vscreen = context_priv->vscreen;

   tex = vscreen->texture_from_drawable(vscreen, (void *)drawable);
   dirty_area = vscreen->get_dirty_area(vscreen);

   memset(&surf_templ, 0, sizeof(surf_templ));
   surf_templ.format = tex->format;
   surf = pipe->create_surface(pipe, tex, &surf_templ);

   if (!surf)
      return BadDrawable;

   /*
    * Some apps (mplayer) hit these asserts because they call
    * this function after the window has been resized by the WM
    * but before they've handled the corresponding XEvent and
    * know about the new dimensions. The output should be clipped
    * until the app updates destw and desth.
    */
   /*
   assert(destx + destw - 1 < drawable_surface->width);
   assert(desty + desth - 1 < drawable_surface->height);
    */

   RecursiveEndFrame(surface_priv);

   context_priv->decoder->flush(context_priv->decoder);

   vl_compositor_clear_layers(cstate);
   vl_compositor_set_buffer_layer(cstate, compositor, 0, surface_priv->video_buffer,
                                  &src_rect, NULL, VL_COMPOSITOR_WEAVE);

   if (subpicture_priv) {
      XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture);

      assert(subpicture_priv->surface == surface);

      if (subpicture_priv->palette)
         vl_compositor_set_palette_layer(cstate, compositor, 1, subpicture_priv->sampler, subpicture_priv->palette,
                                         &subpicture_priv->src_rect, &subpicture_priv->dst_rect, true);
      else
         vl_compositor_set_rgba_layer(cstate, compositor, 1, subpicture_priv->sampler,
                                      &subpicture_priv->src_rect, &subpicture_priv->dst_rect, NULL);

      surface_priv->subpicture = NULL;
      subpicture_priv->surface = NULL;
   }

   // Workaround for r600g, there seems to be a bug in the fence refcounting code
   pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL);

   vl_compositor_set_layer_dst_area(cstate, 0, &dst_rect);
   vl_compositor_set_layer_dst_area(cstate, 1, &dst_rect);
   vl_compositor_render(cstate, compositor, surf, dirty_area, true);

   pipe->flush(pipe, &surface_priv->fence, 0);

   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface);

   pipe->screen->flush_frontbuffer(pipe->screen, tex, 0, 0,
                                   vscreen->get_private(vscreen), NULL);

   if(dump_window == -1) {
      dump_window = debug_get_num_option("XVMC_DUMP", 0);
   }

   if(dump_window) {
      static unsigned int framenum = 0;
      char cmd[256];

      sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum);
      if (system(cmd) != 0)
         XVMC_MSG(XVMC_ERR, "[XvMC] Dumping surface %p failed.\n", surface);
   }

   XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface);

   return Success;
}
Пример #16
0
PUBLIC
Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
                            unsigned short width, unsigned short height, int xvimage_id)
{
   XvMCContextPrivate *context_priv;
   XvMCSubpicturePrivate *subpicture_priv;
   struct pipe_context *pipe;
   struct pipe_resource tex_templ, *tex;
   struct pipe_sampler_view sampler_templ;
   Status ret;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture);

   assert(dpy);

   if (!context)
      return XvMCBadContext;

   context_priv = context->privData;
   pipe = context_priv->pipe;

   if (!subpicture)
      return XvMCBadSubpicture;

   if (width > context_priv->subpicture_max_width ||
       height > context_priv->subpicture_max_height)
      return BadValue;

   ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id);
   if (ret != Success)
      return ret;

   subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate));
   if (!subpicture_priv)
      return BadAlloc;

   memset(&tex_templ, 0, sizeof(tex_templ));
   tex_templ.target = PIPE_TEXTURE_2D;
   tex_templ.format = XvIDToPipe(xvimage_id);
   tex_templ.last_level = 0;
   if (pipe->screen->get_video_param(pipe->screen,
                                     PIPE_VIDEO_PROFILE_UNKNOWN,
                                     PIPE_VIDEO_ENTRYPOINT_UNKNOWN,
                                     PIPE_VIDEO_CAP_NPOT_TEXTURES)) {
      tex_templ.width0 = width;
      tex_templ.height0 = height;
   }
   else {
      tex_templ.width0 = util_next_power_of_two(width);
      tex_templ.height0 = util_next_power_of_two(height);
   }
   tex_templ.depth0 = 1;
   tex_templ.array_size = 1;
   tex_templ.usage = PIPE_USAGE_DYNAMIC;
   tex_templ.bind = PIPE_BIND_SAMPLER_VIEW;
   tex_templ.flags = 0;

   tex = pipe->screen->resource_create(pipe->screen, &tex_templ);

   memset(&sampler_templ, 0, sizeof(sampler_templ));
   u_sampler_view_default_template(&sampler_templ, tex, tex->format);

   subpicture_priv->sampler = pipe->create_sampler_view(pipe, tex, &sampler_templ);
   pipe_resource_reference(&tex, NULL);
   if (!subpicture_priv->sampler) {
      FREE(subpicture_priv);
      return BadAlloc;
   }

   subpicture_priv->context = context;
   subpicture->subpicture_id = XAllocID(dpy);
   subpicture->context_id = context->context_id;
   subpicture->xvimage_id = xvimage_id;
   subpicture->width = width;
   subpicture->height = height;
   subpicture->num_palette_entries = NumPaletteEntries4XvID(xvimage_id);
   subpicture->entry_bytes = PipeToComponentOrder(tex_templ.format, subpicture->component_order);
   subpicture->privData = subpicture_priv;

   if (subpicture->num_palette_entries > 0) {
      tex_templ.target = PIPE_TEXTURE_1D;
      tex_templ.format = PIPE_FORMAT_R8G8B8X8_UNORM;
      tex_templ.width0 = subpicture->num_palette_entries;
      tex_templ.height0 = 1;
      tex_templ.usage = PIPE_USAGE_DEFAULT;

      tex = pipe->screen->resource_create(pipe->screen, &tex_templ);

      memset(&sampler_templ, 0, sizeof(sampler_templ));
      u_sampler_view_default_template(&sampler_templ, tex, tex->format);
      sampler_templ.swizzle_a = PIPE_SWIZZLE_ONE;
      subpicture_priv->palette = pipe->create_sampler_view(pipe, tex, &sampler_templ);
      pipe_resource_reference(&tex, NULL);
      if (!subpicture_priv->sampler) {
         FREE(subpicture_priv);
         return BadAlloc;
      }
   }

   SyncHandle();

   XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture);

   return Success;
}
Пример #17
0
PUBLIC
Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure,
                         XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface,
                         unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock,
                         XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks
)
{
   struct pipe_mpeg12_macroblock mb[num_macroblocks];
   struct pipe_video_codec *decoder;
   struct pipe_mpeg12_picture_desc desc;

   XvMCContextPrivate *context_priv;
   XvMCSurfacePrivate *target_surface_priv;
   XvMCSurfacePrivate *past_surface_priv;
   XvMCSurfacePrivate *future_surface_priv;
   XvMCMacroBlock *xvmc_mb;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n",
            target_surface, past_surface, future_surface);

   assert(dpy);

   if (!context || !context->privData)
      return XvMCBadContext;
   if (!target_surface || !target_surface->privData)
      return XvMCBadSurface;

   if (picture_structure != XVMC_TOP_FIELD &&
       picture_structure != XVMC_BOTTOM_FIELD &&
       picture_structure != XVMC_FRAME_PICTURE)
      return BadValue;
   /* Bkwd pred equivalent to fwd (past && !future) */
   if (future_surface && !past_surface)
      return BadMatch;

   assert(context->context_id == target_surface->context_id);
   assert(!past_surface || context->context_id == past_surface->context_id);
   assert(!future_surface || context->context_id == future_surface->context_id);

   assert(macroblocks);
   assert(blocks);

   assert(macroblocks->context_id == context->context_id);
   assert(blocks->context_id == context->context_id);

   assert(flags == 0 || flags == XVMC_SECOND_FIELD);

   context_priv = context->privData;
   decoder = context_priv->decoder;

   target_surface_priv = target_surface->privData;
   past_surface_priv = past_surface ? past_surface->privData : NULL;
   future_surface_priv = future_surface ? future_surface->privData : NULL;

   assert(target_surface_priv->context == context);
   assert(!past_surface || past_surface_priv->context == context);
   assert(!future_surface || future_surface_priv->context == context);

   // call end frame on all referenced frames
   if (past_surface)
      RecursiveEndFrame(past_surface->privData);

   if (future_surface)
      RecursiveEndFrame(future_surface->privData);

   xvmc_mb = macroblocks->macro_blocks + first_macroblock;

   /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
   if (target_surface_priv->picture_structure > 0 && (
       target_surface_priv->picture_structure != picture_structure ||
       target_surface_priv->ref[0] != past_surface ||
       target_surface_priv->ref[1] != future_surface ||
       (xvmc_mb->x == 0 && xvmc_mb->y == 0))) {

      // If they change anyway we must assume that the current frame is ended
      RecursiveEndFrame(target_surface_priv);
   }

   target_surface_priv->ref[0] = past_surface;
   target_surface_priv->ref[1] = future_surface;

   if (target_surface_priv->picture_structure)
      GetPictureDescription(target_surface_priv, &desc);
   else {
      target_surface_priv->picture_structure = picture_structure;
      GetPictureDescription(target_surface_priv, &desc);
      decoder->begin_frame(decoder, target_surface_priv->video_buffer, &desc.base);
   }

   MacroBlocksToPipe(context_priv, target_surface_priv, picture_structure,
                     xvmc_mb, blocks, mb, num_macroblocks);

   context_priv->decoder->decode_macroblock(context_priv->decoder,
                                            target_surface_priv->video_buffer,
                                            &desc.base,
                                            &mb[0].base, num_macroblocks);

   XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface);

   return Success;
}
Пример #18
0
PUBLIC
Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
{
   XvMCContextPrivate *context_priv;
   struct pipe_context *pipe;
   XvMCSurfacePrivate *surface_priv;
   struct pipe_video_buffer tmpl;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface);

   assert(dpy);

   if (!context)
      return XvMCBadContext;
   if (!surface)
      return XvMCBadSurface;

   context_priv = context->privData;
   pipe = context_priv->pipe;

   surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
   if (!surface_priv)
      return BadAlloc;

   memset(&tmpl, 0, sizeof(tmpl));
   tmpl.buffer_format = pipe->screen->get_video_param
   (
      pipe->screen,
      context_priv->decoder->profile,
      context_priv->decoder->entrypoint,
      PIPE_VIDEO_CAP_PREFERED_FORMAT
   );
   tmpl.chroma_format = context_priv->decoder->chroma_format;
   tmpl.width = context_priv->decoder->width;
   tmpl.height = context_priv->decoder->height;
   tmpl.interlaced = pipe->screen->get_video_param
   (
      pipe->screen,
      context_priv->decoder->profile,
      context_priv->decoder->entrypoint,
      PIPE_VIDEO_CAP_PREFERS_INTERLACED
   );

   surface_priv->video_buffer = pipe->create_video_buffer(pipe, &tmpl);
   if (!surface_priv->video_buffer) {
      FREE(surface_priv);
      return BadAlloc;
   }
   surface_priv->context = context;

   surface->surface_id = XAllocID(dpy);
   surface->context_id = context->context_id;
   surface->surface_type_id = context->surface_type_id;
   surface->width = context->width;
   surface->height = context->height;
   surface->privData = surface_priv;

   SyncHandle();

   XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface);

   return Success;
}
Пример #19
0
static Status Validate(Display *dpy, XvPortID port, int surface_type_id,
                       unsigned int width, unsigned int height, int flags,
                       bool *found_port, int *screen, int *chroma_format,
                       int *mc_type, int *surface_flags,
                       unsigned short *subpic_max_w,
                       unsigned short *subpic_max_h)
{
   bool found_surface = false;
   XvAdaptorInfo *adaptor_info;
   unsigned int num_adaptors;
   int num_types;
   unsigned int max_width = 0, max_height = 0;
   Status ret;

   assert(dpy);
   assert(found_port);
   assert(screen);
   assert(chroma_format);
   assert(mc_type);
   assert(surface_flags);
   assert(subpic_max_w);
   assert(subpic_max_h);

   *found_port = false;

   for (int i = 0; i < XScreenCount(dpy); ++i) {
      ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info);
      if (ret != Success)
         return ret;

      for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j) {
         for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k) {
            XvMCSurfaceInfo *surface_info;

            if (adaptor_info[j].base_id + k != port)
               continue;

            *found_port = true;

            surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);
            if (!surface_info) {
               XvFreeAdaptorInfo(adaptor_info);
               return BadAlloc;
            }

            for (int l = 0; l < num_types && !found_surface; ++l) {
               if (surface_info[l].surface_type_id != surface_type_id)
                  continue;

               found_surface = true;
               max_width = surface_info[l].max_width;
               max_height = surface_info[l].max_height;
               *chroma_format = surface_info[l].chroma_format;
               *mc_type = surface_info[l].mc_type;
               *surface_flags = surface_info[l].flags;
               *subpic_max_w = surface_info[l].subpicture_max_width;
               *subpic_max_h = surface_info[l].subpicture_max_height;
               *screen = i;

               XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \
                                    "[XvMC]   screen=%u, port=%u\n" \
                                    "[XvMC]   id=0x%08X\n" \
                                    "[XvMC]   max width=%u, max height=%u\n" \
                                    "[XvMC]   chroma format=0x%08X\n" \
                                    "[XvMC]   acceleration level=0x%08X\n" \
                                    "[XvMC]   flags=0x%08X\n" \
                                    "[XvMC]   subpicture max width=%u, max height=%u\n",
                                    i, port, surface_type_id, max_width, max_height, *chroma_format,
                                    *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h);
            }

            free(surface_info);
         }
      }

      XvFreeAdaptorInfo(adaptor_info);
   }

   if (!*found_port) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n");
      return XvBadPort;
   }
   if (!found_surface) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n");
      return BadMatch;
   }
   if (width > max_width || height > max_height) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n",
               width, height, max_width, max_height);
      return BadValue;
   }
   if (flags != XVMC_DIRECT && flags != 0) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags);
      return BadValue;
   }

   return Success;
}
Пример #20
0
PUBLIC
Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
                         int width, int height, int flags, XvMCContext *context)
{
   bool found_port;
   int scrn = 0;
   int chroma_format = 0;
   int mc_type = 0;
   int surface_flags = 0;
   unsigned short subpic_max_w = 0;
   unsigned short subpic_max_h = 0;
   Status ret;
   struct vl_screen *vscreen;
   struct pipe_context *pipe;
   struct pipe_video_codec templat = {0};
   XvMCContextPrivate *context_priv;
   vl_csc_matrix csc;

   XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context);

   assert(dpy);

   if (!context)
      return XvMCBadContext;

   ret = Validate(dpy, port, surface_type_id, width, height, flags,
                  &found_port, &scrn, &chroma_format, &mc_type, &surface_flags,
                  &subpic_max_w, &subpic_max_h);

   /* Success and XvBadPort have the same value */
   if (ret != Success || !found_port)
      return ret;

   /* XXX: Current limits */
   if (chroma_format != XVMC_CHROMA_FORMAT_420) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n");
      return BadImplementation;
   }
   if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n");
      return BadImplementation;
   }
   if (surface_flags & XVMC_INTRA_UNSIGNED) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n");
      return BadImplementation;
   }

   context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
   if (!context_priv)
      return BadAlloc;

   /* TODO: Reuse screen if process creates another context */
   vscreen = vl_screen_create(dpy, scrn);

   if (!vscreen) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n");
      FREE(context_priv);
      return BadAlloc;
   }

   pipe = vscreen->pscreen->context_create(vscreen->pscreen, vscreen, 0);
   if (!pipe) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n");
      vl_screen_destroy(vscreen);
      FREE(context_priv);
      return BadAlloc;
   }

   templat.profile = ProfileToPipe(mc_type);
   templat.entrypoint = (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC;
   templat.chroma_format = FormatToPipe(chroma_format);
   templat.width = width;
   templat.height = height;
   templat.max_references = 2;
   templat.expect_chunked_decode = true;

   context_priv->decoder = pipe->create_video_codec(pipe, &templat);

   if (!context_priv->decoder) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n");
      pipe->destroy(pipe);
      vl_screen_destroy(vscreen);
      FREE(context_priv);
      return BadAlloc;
   }

   if (!vl_compositor_init(&context_priv->compositor, pipe)) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n");
      context_priv->decoder->destroy(context_priv->decoder);
      pipe->destroy(pipe);
      vl_screen_destroy(vscreen);
      FREE(context_priv);
      return BadAlloc;
   }

   if (!vl_compositor_init_state(&context_priv->cstate, pipe)) {
      XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor state.\n");
      vl_compositor_cleanup(&context_priv->compositor);
      context_priv->decoder->destroy(context_priv->decoder);
      pipe->destroy(pipe);
      vl_screen_destroy(vscreen);
      FREE(context_priv);
      return BadAlloc;
   }


   context_priv->color_standard =
      debug_get_bool_option("G3DVL_NO_CSC", FALSE) ?
      VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601;
   context_priv->procamp = vl_default_procamp;

   vl_csc_get_matrix
   (
      context_priv->color_standard,
      &context_priv->procamp, true, &csc
   );
   vl_compositor_set_csc_matrix(&context_priv->cstate, (const vl_csc_matrix *)&csc);

   context_priv->vscreen = vscreen;
   context_priv->pipe = pipe;
   context_priv->subpicture_max_width = subpic_max_w;
   context_priv->subpicture_max_height = subpic_max_h;

   context->context_id = XAllocID(dpy);
   context->surface_type_id = surface_type_id;
   context->width = width;
   context->height = height;
   context->flags = flags;
   context->port = port;
   context->privData = context_priv;

   SyncHandle();

   XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context);

   return Success;
}