Beispiel #1
0
bool CVDPAU::ConfigOutputMethod(AVCodecContext *avctx, AVFrame *pFrame)
{
  VdpStatus vdp_st;

  if (m_vdpauOutputMethod == OUTPUT_PIXMAP)
    return true;

  FiniOutputMethod();

  MakePixmap(avctx->width,avctx->height);

  vdp_st = vdp_presentation_queue_target_create_x11(vdp_device,
                                                    m_Pixmap, //x_window,
                                                    &vdp_flip_target);
  if (CheckStatus(vdp_st, __LINE__))
    return false;

  vdp_st = vdp_presentation_queue_create(vdp_device,
                                         vdp_flip_target,
                                         &vdp_flip_queue);
  if (CheckStatus(vdp_st, __LINE__))
    return false;

  totalAvailableOutputSurfaces = 0;

  int tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES;
  if (vid_width == FULLHD_WIDTH)
    tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES_FOR_FULLHD;

  // Creation of outputSurfaces
  for (int i = 0; i < NUM_OUTPUT_SURFACES && i < tmpMaxOutputSurfaces; i++)
  {
    vdp_st = vdp_output_surface_create(vdp_device,
                                       VDP_RGBA_FORMAT_B8G8R8A8,
                                       OutWidth,
                                       OutHeight,
                                       &outputSurfaces[i]);
    if (CheckStatus(vdp_st, __LINE__))
      return false;
    totalAvailableOutputSurfaces++;
  }
  CLog::Log(LOGNOTICE, " (VDPAU) Total Output Surfaces Available: %i of a max (tmp: %i const: %i)",
                       totalAvailableOutputSurfaces,
                       tmpMaxOutputSurfaces,
                       NUM_OUTPUT_SURFACES);

  surfaceNum = presentSurfaceNum = 0;
  outputSurface = presentSurface = VDP_INVALID_HANDLE;
  videoMixer = VDP_INVALID_HANDLE;

  m_vdpauOutputMethod = OUTPUT_PIXMAP;

  return true;
}
Beispiel #2
0
bool CVDPAU::ConfigVDPAU(AVCodecContext* avctx, int ref_frames)
{
  FiniVDPAUOutput();

  VdpStatus vdp_st;
  VdpDecoderProfile vdp_decoder_profile;
  vid_width = avctx->width;
  vid_height = avctx->height;

  past[1] = past[0] = current = future = NULL;
  CLog::Log(LOGNOTICE, " (VDPAU) screenWidth:%i vidWidth:%i",OutWidth,vid_width);
  CLog::Log(LOGNOTICE, " (VDPAU) screenHeight:%i vidHeight:%i",OutHeight,vid_height);
  ReadFormatOf(avctx->pix_fmt, vdp_decoder_profile, vdp_chroma_type);

  if(avctx->pix_fmt == PIX_FMT_VDPAU_H264)
  {
     max_references = ref_frames;
     if (max_references > 16) max_references = 16;
     if (max_references < 5)  max_references = 5;
  }
  else
    max_references = 2;

  vdp_st = vdp_decoder_create(vdp_device,
                              vdp_decoder_profile,
                              vid_width,
                              vid_height,
                              max_references,
                              &decoder);
  CHECK_VDPAU_RETURN(vdp_st, false);

  vdp_st = vdp_presentation_queue_target_create_x11(vdp_device,
                                                    m_Pixmap, //x_window,
                                                    &vdp_flip_target);
  CHECK_VDPAU_RETURN(vdp_st, false);

  vdp_st = vdp_presentation_queue_create(vdp_device,
                                         vdp_flip_target,
                                         &vdp_flip_queue);
  CHECK_VDPAU_RETURN(vdp_st, false);

  totalAvailableOutputSurfaces = 0;

  int tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES;
  if (vid_width == FULLHD_WIDTH)
    tmpMaxOutputSurfaces = NUM_OUTPUT_SURFACES_FOR_FULLHD;

  // Creation of outputSurfaces
  for (int i = 0; i < NUM_OUTPUT_SURFACES && i < tmpMaxOutputSurfaces; i++)
  {
    vdp_st = vdp_output_surface_create(vdp_device,
                                       VDP_RGBA_FORMAT_B8G8R8A8,
                                       OutWidth,
                                       OutHeight,
                                       &outputSurfaces[i]);
    CHECK_VDPAU_RETURN(vdp_st, false);
    totalAvailableOutputSurfaces++;
  }
  CLog::Log(LOGNOTICE, " (VDPAU) Total Output Surfaces Available: %i of a max (tmp: %i const: %i)",
                       totalAvailableOutputSurfaces,
                       tmpMaxOutputSurfaces,
                       NUM_OUTPUT_SURFACES);

  surfaceNum = presentSurfaceNum = 0;
  outputSurface = outputSurfaces[surfaceNum];

vdpauConfigured = true;
  return true;
}
Beispiel #3
0
int main(void)
{

    VdpDevice device;
    VdpBitmapSurface bmp_surface;
    VdpOutputSurface out_surface;

    const uint8_t bmp_1[] = {
        0x00, 0x01, 0x02, 0x03,
        0x14, 0x15, 0x16, 0x17,
        0x28, 0x29, 0x2a, 0x2b,
        0x3c, 0x3d, 0x3e, 0x3f
    };
    const void * const source_data_bmp[] = { bmp_1 };
    uint32_t source_pitches_bmp[] = { 4 };

    const uint32_t black_4x4[] = {
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xff000000
    };
    const void * const source_data_black[] = { black_4x4 };
    uint32_t source_pitches_black[] = { 4 * 4 };

    ASSERT_OK(vdpau_init_functions(&device, NULL, 0));
    // create surfaces
    ASSERT_OK(vdp_bitmap_surface_create(device, VDP_RGBA_FORMAT_A8, 4, 4, 1, &bmp_surface));
    ASSERT_OK(vdp_output_surface_create(device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, &out_surface));
    // upload data
    ASSERT_OK(vdp_bitmap_surface_put_bits_native(bmp_surface, source_data_bmp, source_pitches_bmp, NULL));
    ASSERT_OK(vdp_output_surface_put_bits_native(out_surface, source_data_black, source_pitches_black, NULL));

    VdpOutputSurfaceRenderBlendState blend_state = {
        .blend_factor_source_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA,
        .blend_factor_destination_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
        .blend_factor_source_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
        .blend_factor_destination_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA,
        .blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
        .blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
        .blend_constant = {0, 0, 0, 0}
    };

    VdpColor color[] = {{0, 1.0, 0, 1.0}};
    ASSERT_OK(vdp_output_surface_render_bitmap_surface(out_surface, NULL, bmp_surface, NULL,
                color, &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0));

    const uint32_t expected_result[] = {
        0x00000000, 0x02000100, 0x04000200, 0x06000300,
        0x28001400, 0x2a001500, 0x2c001600, 0x2e001700,
        0x50002800, 0x52002900, 0x54002a00, 0x56002b00,
        0x78003c00, 0x7a003d00, 0x7c003e00, 0x7e003f00
    };

    uint32_t result[16];
    void * const dest_data[] = { result };
    ASSERT_OK(vdp_output_surface_get_bits_native(out_surface, NULL, dest_data, source_pitches_black));

    printf("=== expected ===\n");
    for (int k = 0; k < 16; k ++) {
        printf(" %08x", expected_result[k]);
        if (k % 4 == 3) printf("\n");
    }
    printf("--- actual ---\n");
    for (int k = 0; k < 16; k ++) {
        printf(" %08x", result[k]);
        if (k % 4 == 3) printf("\n");
    }
    printf("==========\n");

    if (memcmp(expected_result, result, sizeof(expected_result))) {
        printf("fail\n");
        return 1;
    }

    printf("pass\n");
    return 0;
}
Beispiel #4
0
int main(void)
{
    VdpDevice device;
    VdpStatus st = vdpau_init_functions(&device, NULL, 0);
    assert (VDP_STATUS_OK == st);

    VdpOutputSurface out_surface_1;
    VdpOutputSurface out_surface_2;

    ASSERT_OK(vdp_output_surface_create(device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, &out_surface_1));
    ASSERT_OK(vdp_output_surface_create(device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, &out_surface_2));

    uint32_t black_box[] = {
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xff000000
    };

    uint32_t two_red_dots[] = {
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xffff0000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xff000000,
        0xff000000, 0xff000000, 0xff000000, 0xffff0000
    };

    const void * const source_data_1[] = {black_box};
    const void * const source_data_2[] = {two_red_dots};
    uint32_t source_pitches[] = { 4 * 4 };

    // upload data
    ASSERT_OK(vdp_output_surface_put_bits_native(out_surface_1, source_data_1, source_pitches, NULL));
    ASSERT_OK(vdp_output_surface_put_bits_native(out_surface_2, source_data_2, source_pitches, NULL));

    // render
    VdpOutputSurfaceRenderBlendState blend_state = {
        .struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION,
        .blend_factor_source_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
        .blend_factor_source_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
        .blend_factor_destination_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO,
        .blend_factor_destination_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO,
        .blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
        .blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
        .blend_constant = {0, 0, 0, 0}
    };

    ASSERT_OK(vdp_output_surface_render_output_surface(out_surface_1, NULL, out_surface_2, NULL,
                NULL, &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0));

    // get data back
    uint32_t receive_buf[16];
    void * const dest_data[] = {receive_buf};
    ASSERT_OK(vdp_output_surface_get_bits_native(out_surface_1, NULL, dest_data, source_pitches));

    printf("output surface\n");
    for (int k = 0; k < 16; k ++) {
        printf("%x ", receive_buf[k]);
        if (3 == k % 4) printf("\n");
    }
    printf("----------\n");
    for (int k = 0; k < 16; k ++) {
        printf("%x ", two_red_dots[k]);
        if (3 == k % 4) printf("\n");
    }

    // compare recieve_buf with two_red_dots
    if (memcmp(receive_buf, two_red_dots, 4*4*4)) {
        printf("fail\n");
        return 1;
    }

    // Check bitmap surface rendering smoothing issue
    VdpBitmapSurface bmp_surface;
    ASSERT_OK(vdp_bitmap_surface_create(device, VDP_RGBA_FORMAT_B8G8R8A8, 4, 4, 1, &bmp_surface));
    ASSERT_OK(vdp_bitmap_surface_put_bits_native(bmp_surface, source_data_2, source_pitches, NULL));
    VdpOutputSurfaceRenderBlendState blend_state_opaque_copy = {
        .struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION,
        .blend_factor_source_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
        .blend_factor_source_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
        .blend_factor_destination_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO,
        .blend_factor_destination_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO,
        .blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
        .blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD,
        .blend_constant = {0, 0, 0, 0}
    };
    ASSERT_OK(vdp_output_surface_render_bitmap_surface(out_surface_1, NULL, bmp_surface, NULL,
                NULL, &blend_state_opaque_copy, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0));
    ASSERT_OK(vdp_output_surface_get_bits_native(out_surface_1, NULL, dest_data, source_pitches));

    printf("bitmap surface\n");
    for (int k = 0; k < 16; k ++) {
        printf("%x ", receive_buf[k]);
        if (3 == k % 4) printf("\n");
    }
    printf("----------\n");
    for (int k = 0; k < 16; k ++) {
        printf("%x ", two_red_dots[k]);
        if (3 == k % 4) printf("\n");
    }

    if (memcmp(receive_buf, two_red_dots, 4*4*4)) {
        printf("fail\n");
        return 2;
    }

    printf("pass\n");
    return 0;
}
Beispiel #5
0
int main(int argc, char **argv) {
  int width = 1280, height = 544;
  Display *display = XOpenDisplay(NULL);

  Window root = XDefaultRootWindow(display);
  Window window = XCreateSimpleWindow(
      display, root, 0, 0, 1280, 544, 0, 0, 0);
  XSelectInput(display, window, ExposureMask | KeyPressMask);
  XMapWindow(display, window);
  XSync(display, 0);

  VdpDevice dev;

  mark("vdp_device_create_x11\n");
  int ret = vdp_device_create_x11(display, 0, &dev, &vdp_get_proc_address);
  assert(ret == VDP_STATUS_OK);

#define get(id, func) \
  ret = vdp_get_proc_address(dev, id, (void **)&func); \
  assert(ret == VDP_STATUS_OK);

  get(VDP_FUNC_ID_DECODER_CREATE, vdp_decoder_create);
  get(VDP_FUNC_ID_DECODER_DESTROY, vdp_decoder_destroy);
  get(VDP_FUNC_ID_DECODER_RENDER, vdp_decoder_render);

  get(VDP_FUNC_ID_VIDEO_MIXER_CREATE, vdp_video_mixer_create);
  get(VDP_FUNC_ID_VIDEO_MIXER_DESTROY, vdp_video_mixer_destroy);
  get(VDP_FUNC_ID_VIDEO_MIXER_RENDER, vdp_video_mixer_render);

  get(VDP_FUNC_ID_VIDEO_SURFACE_CREATE, vdp_video_surface_create);
  get(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, vdp_video_surface_destroy);
  get(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, vdp_video_surface_get_bits_ycbcr);

  get(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, vdp_output_surface_create);
  get(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, vdp_output_surface_destroy);
  get(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE, vdp_output_surface_get_bits_native);

  get(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE, vdp_presentation_queue_create);
  get(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY, vdp_presentation_queue_destroy);
  get(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY, vdp_presentation_queue_display);
  get(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, vdp_presentation_queue_target_create_x11);
  get(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, vdp_presentation_queue_block_until_surface_idle);
  get(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME, vdp_presentation_queue_get_time);

#undef get

  VdpDecoder dec;
  VdpVideoSurface video[16];
  VdpOutputSurface output;
  VdpPresentationQueue queue;
  VdpPresentationQueueTarget target;
  VdpVideoMixer mixer;

  VdpVideoMixerFeature mixer_features[] = {
  };
  VdpVideoMixerParameter mixer_params[] = {
    VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH,
    VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT,
    VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
  };
  int zero = 0;
  const void *mixer_param_vals[] = {
    &width,
    &height,
    &zero
  };

  mark("vdp_decoder_create\n");
  ret = vdp_decoder_create(dev, VDP_DECODER_PROFILE_H264_MAIN, 1280, 544, 6, &dec);
  assert(ret == VDP_STATUS_OK);

  int i;
  for (i = 0; i < 16; i++) {
    mark("vdp_video_surface_create: %d\n", i);
    ret = vdp_video_surface_create(dev, VDP_CHROMA_TYPE_420, 1280, 544, &video[i]);
    assert(ret == VDP_STATUS_OK);
    mark(" <-- %d\n", video[i]);
  }


  mark("vdp_output_surface_create\n");
  ret = vdp_output_surface_create(dev, VDP_RGBA_FORMAT_B8G8R8A8, 1280, 544, &output);
  assert(ret == VDP_STATUS_OK);

  mark("vdp_presentation_queue_target_create_x11\n");
  ret = vdp_presentation_queue_target_create_x11(dev, window, &target);
  assert(ret == VDP_STATUS_OK);

  mark("vdp_presentation_queue_create\n");
  ret = vdp_presentation_queue_create(dev, target, &queue);
  assert(ret == VDP_STATUS_OK);

  mark("vdp_video_mixer_create\n");
  ret = vdp_video_mixer_create(dev, sizeof(mixer_features)/sizeof(mixer_features[0]), mixer_features, sizeof(mixer_params)/sizeof(mixer_params[0]), mixer_params, mixer_param_vals, &mixer);
  assert(ret == VDP_STATUS_OK);


  assert(argc > 1);
  int fd = open(argv[1], O_RDONLY);
  struct stat statbuf;
  assert(fstat(fd, &statbuf) == 0);
  void *addr = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
  void *orig_addr = addr;

  mark("mmap file addr: 0x%p size: 0x%lx\n", addr, statbuf.st_size);

  //printf("mmap'd file of size: %ld\n", statbuf.st_size);

  VdpPictureInfoH264 info = {
    .slice_count = 1,
    .field_order_cnt = { 65536, 65536 },
    .is_reference = 1,
    .frame_num = -1,
    .field_pic_flag = 0,
    .bottom_field_flag = 0,
    .num_ref_frames = 6,
    .mb_adaptive_frame_field_flag = 0,
    .constrained_intra_pred_flag = 0,
    .weighted_pred_flag = 0,
    .weighted_bipred_idc = 0,
    .frame_mbs_only_flag = 1,
    .transform_8x8_mode_flag = 0,
    .chroma_qp_index_offset = 0,
    .second_chroma_qp_index_offset = 0,
    .pic_init_qp_minus26 = 0,
    .num_ref_idx_l0_active_minus1 = 0,
    .num_ref_idx_l1_active_minus1 = 0,
    .log2_max_frame_num_minus4 = 5,
    .pic_order_cnt_type = 0,
    .log2_max_pic_order_cnt_lsb_minus4 = 6,
    .delta_pic_order_always_zero_flag = 0,
    .direct_8x8_inference_flag = 1,
    .entropy_coding_mode_flag = 1,
    .pic_order_present_flag = 0,
    .deblocking_filter_control_present_flag = 1,
    .redundant_pic_cnt_present_flag = 0,
  };
  int j;
  for (j = 0; j < 6; ++j) {
    int k;

    for (k = 0; k < 16; ++k)
      info.scaling_lists_4x4[j][k] = 16;
  }

  for (j = 0; j < 2; ++j) {
    int k;

    for (k = 0; k < 64; ++k)
      info.scaling_lists_8x8[j][k] = 16;
  }

  for (j = 0; j < 16; ++j)
    info.referenceFrames[j].surface = VDP_INVALID_HANDLE;


  mark("vdp_presentation_queue_get_time\n");
  VdpTime t;
  ret = vdp_presentation_queue_get_time(queue, &t);
  assert(ret == VDP_STATUS_OK);

  fprintf(stderr, "Start time: %ld\n", t);

  int vframe = 0;

  while ((addr - orig_addr) < statbuf.st_size) {
    int size = ntohl(*(int *)addr);
    addr += 4;
    int nal_type = (*(char *)addr) & 0x1F;
    int nal_ref_idc = (*(char *)addr) >> 5;
    if (nal_type != 1 && nal_type != 5) {
      //fprintf(stderr, "Skipping NAL type %d, size: %d\n", nal_type, size);
      addr += size;
      continue;
    }
    //fprintf(stderr, "Processing NAL type %d, ref_idc: %d, size: %d\n", nal_type, nal_ref_idc, size);

    int bit_offset = 8;
    ue(addr, &bit_offset);
    int slice_type = ue(addr, &bit_offset);
    mark("nal_type: %d, ref_idc: %d, size: %d, slice_type: %d\n", nal_type, nal_ref_idc, size, slice_type);
    //fprintf(stderr, "Slice type: %d\n", slice_type);
    ue(addr, &bit_offset);
    info.frame_num = read_bits(addr, &bit_offset, info.log2_max_frame_num_minus4 + 4);
    if (nal_type == 5) {
      ue(addr, &bit_offset);
      info.frame_num = 0;
      for (j = 0; j < 16; ++j)
        info.referenceFrames[j].surface = VDP_INVALID_HANDLE;
    }

    uint32_t poc_lsb = read_bits(addr, &bit_offset, info.log2_max_pic_order_cnt_lsb_minus4 + 4);
    info.field_order_cnt[0] = (1 << 16) + poc_lsb;
    info.field_order_cnt[1] = (1 << 16) + poc_lsb;

    info.is_reference = nal_ref_idc != 0;

    VdpBitstreamBuffer buffer[2];
    static const char header[3] = {0, 0, 1};
    buffer[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
    buffer[0].bitstream = header;
    buffer[0].bitstream_bytes = sizeof(header);
    buffer[1].struct_version = VDP_BITSTREAM_BUFFER_VERSION;
    buffer[1].bitstream = addr;
    buffer[1].bitstream_bytes = size;
    mark("vdp_decoder_render: %d\n", video[vframe]);
    ret = vdp_decoder_render(dec, video[vframe], (void*)&info, 2, buffer);
    assert(ret == VDP_STATUS_OK);

    mark("vdp_video_mixer_render\n");
    ret = vdp_video_mixer_render(
        mixer,
        VDP_INVALID_HANDLE, NULL,
        VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME,
        0, NULL,
        video[vframe],
        0, NULL,
        NULL,
        output,
        NULL,
        NULL,
        0, NULL);
    assert(ret == VDP_STATUS_OK);

    t += 1000000000ULL;
    mark("vdp_presentation_queue_display\n");
    ret = vdp_presentation_queue_display(queue, output, 1280, 544, t);
    assert(ret == VDP_STATUS_OK);

    addr += size;

    /*
    uint32_t pitches[2] = {1280, 640 * 2};
    uint8_t *data[2];
    for (i = 0; i < 2; i++) {
      data[i] = malloc(1280 * 544 / (i ? 2 : 1));
      assert(data[i]);
    }
    ret = vdp_video_surface_get_bits_ycbcr(video[vframe], VDP_YCBCR_FORMAT_NV12, (void **)data, pitches);
    assert(ret == VDP_STATUS_OK);

    write(1, data[0], 1280 * 544);
    for (i = 0; i < 1280 * 544 / 2; i+=2)
      write(1, data[1] + i, 1);
    for (i = 0; i < 1280 * 544 / 2; i+=2)
      write(1, data[1] + i + 1, 1);
    */

    if (info.is_reference) {
      for (j = 5; j > 0; --j)
        memcpy(&info.referenceFrames[j], &info.referenceFrames[j-1], sizeof(info.referenceFrames[0]));
      info.referenceFrames[0].surface = video[vframe];
      memcpy(info.referenceFrames[0].field_order_cnt, info.field_order_cnt, 2 * sizeof(uint32_t));
      info.referenceFrames[0].frame_idx = info.frame_num;
      info.referenceFrames[0].top_is_reference = 1;
      info.referenceFrames[0].bottom_is_reference = 1;
    }
    vframe = (vframe + 1) % 16;
    //if (vframe > 10) break;
  }

  return 0;
}