commit 88ada263e6b5d380f2b5bb911194cbbfe8499342
Author: Asko Tontti <asko.tontti@NOT>
Date:   Sun Jun 22 21:18:36 2014 +0300

    removed redundant code and replaced wrong variable names

diff --git a/src/api-video-decoder.c b/src/api-video-decoder.c
index 87eba8a..6257fc0 100644
--- a/src/api-video-decoder.c
+++ b/src/api-video-decoder.c
@@ -218,10 +218,8 @@ h264_translate_reference_frames(VdpVideoSurfaceData *dstSurfData, VdpDecoder dec
 
     // reference frames
     for (int k = 0; k < vdppi->num_ref_frames; k ++) {
-        if (VDP_INVALID_HANDLE == vdppi->referenceFrames[k].surface) {
-            reset_va_picture_h264(&pic_param->ReferenceFrames[k]);
+        if (VDP_INVALID_HANDLE == vdppi->referenceFrames[k].surface)
             continue;
-        }
 
         VdpReferenceFrameH264 const *vdp_ref = &(vdppi->referenceFrames[k]);
         VdpVideoSurfaceData *vdpSurfData =
@@ -237,9 +235,9 @@ h264_translate_reference_frames(VdpVideoSurfaceData *dstSurfData, VdpDecoder dec
             int idx = free_list_pop(decoderData->free_list, &decoderData->free_list_head);
             if (-1 == idx)
                 return VDP_STATUS_RESOURCES;
-            dstSurfData->decoder = decoder;
-            dstSurfData->va_surf = decoderData->render_targets[idx];
-            dstSurfData->rt_idx  = idx;
+            vdpSurfData->decoder = decoder;
+            vdpSurfData->va_surf = decoderData->render_targets[idx];
+            vdpSurfData->rt_idx  = idx;
         }
 
         va_ref->picture_id = vdpSurfData->va_surf;

commit 037821143aa7f4bb4d8a75e2911debb69c1875ae
Author: Asko Tontti <asko.tontti@NOT>
Date:   Sun Jun 22 21:15:46 2014 +0300

    added MPEG2 decoding.

diff --git a/src/api-video-decoder.c b/src/api-video-decoder.c
index 8b95aad..87eba8a 100644
--- a/src/api-video-decoder.c
+++ b/src/api-video-decoder.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2013-2014  Rinat Ibragimov
+ * Copyright 2014  Asko Tontti
  *
  * This file is part of libvdpau-va-gl
  *
@@ -59,6 +60,18 @@ vdpDecoderCreate(VdpDevice device, VdpDecoderProfile profile, uint32_t width, ui
     while (! final_try) {
         profile = next_profile;
         switch (profile) {
+        case VDP_DECODER_PROFILE_MPEG2_SIMPLE:
+	    va_profile = VAProfileMPEG2Simple;
+            data->num_render_targets = NUM_RENDER_TARGETS_MPEG2;
+            next_profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
+            break;
+        case VDP_DECODER_PROFILE_MPEG2_MAIN:
+            va_profile = VAProfileMPEG2Main;
+            data->num_render_targets = NUM_RENDER_TARGETS_MPEG2;
+            // there is no more advanced profile, so it's final try
+            final_try = 1;
+            break;
+
         case VDP_DECODER_PROFILE_H264_BASELINE:
             va_profile = VAProfileH264Baseline;
             data->num_render_targets = NUM_RENDER_TARGETS_H264;
@@ -75,6 +88,7 @@ vdpDecoderCreate(VdpDevice device, VdpDecoderProfile profile, uint32_t width, ui
             // there is no more advanced profile, so it's final try
             final_try = 1;
             break;
+
         default:
             traceError("error (%s): decoder %s not implemented\n", __func__,
                        reverse_decoder_profile(profile));
@@ -301,10 +315,10 @@ vdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile, VdpBool
     for (int k = 0; k < num_profiles; k ++) {
         switch (va_profile_list[k]) {
         case VAProfileMPEG2Main:
-            available_profiles.mpeg2_main = 0;
+            available_profiles.mpeg2_main = 1;
             /* fall through */
         case VAProfileMPEG2Simple:
-            available_profiles.mpeg2_simple = 0;
+            available_profiles.mpeg2_simple = 1;
             break;
 
         case VAProfileH264High:
@@ -404,6 +418,340 @@ quit:
 }
 
 static
+VdpStatus
+mpeg2_translate_reference_frames(VdpVideoSurfaceData *dstSurfData, VdpDecoder decoder,
+				 VdpDecoderData *decoderData,
+				 VAPictureParameterBufferMPEG2 *pic_param,
+				 const VdpPictureInfoMPEG1Or2 *vdppi)
+{
+    // take new VA surface from buffer if needed
+    if (VA_INVALID_SURFACE == dstSurfData->va_surf) {
+        int idx = free_list_pop(decoderData->free_list, &decoderData->free_list_head);
+        if (-1 == idx)
+            return VDP_STATUS_RESOURCES;
+        dstSurfData->decoder = decoder;
+        dstSurfData->va_surf = decoderData->render_targets[idx];
+        dstSurfData->rt_idx  = idx;
+    }
+
+    // mark all pictures invalid preliminary
+    pic_param->forward_reference_picture = VA_INVALID_SURFACE;
+    pic_param->backward_reference_picture = VA_INVALID_SURFACE;
+
+    // reference frames
+    if (VDP_INVALID_HANDLE != vdppi->forward_reference) {
+        VdpVideoSurfaceData *vdpSurfData =
+            handle_acquire(vdppi->forward_reference, HANDLETYPE_VIDEO_SURFACE);
+        if (NULL == vdpSurfData) {
+            traceError("error (%s): NULL == vdpSurfData\n", __func__);
+            return VDP_STATUS_ERROR;
+        }
+
+        // take new VA surface from buffer if needed
+        if (VA_INVALID_SURFACE == vdpSurfData->va_surf) {
+            int idx = free_list_pop(decoderData->free_list, &decoderData->free_list_head);
+            if (-1 == idx)
+                return VDP_STATUS_RESOURCES;
+            vdpSurfData->decoder = decoder;
+            vdpSurfData->va_surf = decoderData->render_targets[idx];
+            vdpSurfData->rt_idx  = idx;
+        }
+
+        pic_param->forward_reference_picture = vdpSurfData->va_surf;
+        handle_release(vdppi->forward_reference);
+    }
+
+    if (VDP_INVALID_HANDLE != vdppi->backward_reference) {
+        VdpVideoSurfaceData *vdpSurfData =
+            handle_acquire(vdppi->backward_reference, HANDLETYPE_VIDEO_SURFACE);
+        if (NULL == vdpSurfData) {
+            traceError("error (%s): NULL == vdpSurfData\n", __func__);
+            return VDP_STATUS_ERROR;
+        }
+
+        // take new VA surface from buffer if needed
+        if (VA_INVALID_SURFACE == vdpSurfData->va_surf) {
+            int idx = free_list_pop(decoderData->free_list, &decoderData->free_list_head);
+            if (-1 == idx)
+                return VDP_STATUS_RESOURCES;
+            vdpSurfData->decoder = decoder;
+            vdpSurfData->va_surf = decoderData->render_targets[idx];
+            vdpSurfData->rt_idx  = idx;
+        }
+
+	pic_param->backward_reference_picture = vdpSurfData->va_surf;
+        handle_release(vdppi->backward_reference);
+    }
+
+    return VDP_STATUS_OK;
+}
+
+static
+void
+mpeg2_translate_pic_param(VAPictureParameterBufferMPEG2 *pic_param, uint32_t width, uint32_t height,
+                         const VdpPictureInfoMPEG1Or2 *vdppi)
+{
+        pic_param->horizontal_size              = width;
+	pic_param->vertical_size                = height;
+	pic_param->picture_coding_type          = vdppi->picture_coding_type;
+
+	pic_param->f_code = ((vdppi->f_code[0][0] & 0xf) << 12 |
+			     (vdppi->f_code[0][1] & 0xf) << 8 |
+			     (vdppi->f_code[1][0] & 0xf) << 4 |
+			     (vdppi->f_code[1][1] & 0xf));
+
+#define PCE_FIELDS(fieldname) pic_param->picture_coding_extension.bits.fieldname
+
+	PCE_FIELDS(intra_dc_precision)          = vdppi->intra_dc_precision;
+        PCE_FIELDS(picture_structure)           = vdppi->picture_structure;
+        PCE_FIELDS(top_field_first)             = vdppi->top_field_first;
+        PCE_FIELDS(frame_pred_frame_dct)        = vdppi->frame_pred_frame_dct;
+        PCE_FIELDS(concealment_motion_vectors)  = vdppi->concealment_motion_vectors;
+	PCE_FIELDS(q_scale_type)                = vdppi->q_scale_type;
+	PCE_FIELDS(intra_vlc_format)            = vdppi->intra_vlc_format;
+	PCE_FIELDS(alternate_scan)              = vdppi->alternate_scan;
+
+	/* VDPAU doesn't support field-coded MPEG2 */
+	PCE_FIELDS(repeat_first_field)          = 0;
+	PCE_FIELDS(progressive_frame)           = 0;
+	PCE_FIELDS(is_first_field)              = 0;
+
+#undef PCE_FIELDS
+}
+
+static
+void
+mpeg2_translate_iq_matrix(VAIQMatrixBufferMPEG2 *iq_matrix, const VdpPictureInfoMPEG1Or2 *vdppi)
+{
+    iq_matrix->load_intra_quantiser_matrix = 1;
+    iq_matrix->load_non_intra_quantiser_matrix = 1;
+    iq_matrix->load_chroma_intra_quantiser_matrix = 0;
+    iq_matrix->load_chroma_non_intra_quantiser_matrix = 0;
+
+    for (int j = 0; j < 64; j ++)
+      iq_matrix->intra_quantiser_matrix[j] = vdppi->intra_quantizer_matrix[j];
+    for (int j = 0; j < 64; j ++)
+      iq_matrix->non_intra_quantiser_matrix[j] = vdppi->non_intra_quantizer_matrix[j];
+
+    for (int j = 0; j < 64; j ++)
+      iq_matrix->chroma_intra_quantiser_matrix[j] = 0;
+    for (int j = 0; j < 64; j ++)
+      iq_matrix->chroma_non_intra_quantiser_matrix[j] = 0;
+}
+
+static
+VdpStatus
+vdpDecoderRender_mpeg2(VdpDecoder decoder, VdpDecoderData *decoderData,
+		       VdpVideoSurfaceData *dstSurfData, VdpPictureInfo const *picture_info,
+		       uint32_t bitstream_buffer_count,
+		       VdpBitstreamBuffer const *bitstream_buffers)
+{
+    VdpDeviceData *deviceData = decoderData->deviceData;
+    VADisplay va_dpy = deviceData->va_dpy;
+    VAStatus status;
+    VdpStatus vs, err_code;
+    VdpPictureInfoMPEG1Or2 const *vdppi = (void *)picture_info;
+    uint8_t *merged_bitstream = NULL;
+
+    // preparing picture parameters and IQ matrix
+    VABufferID pic_param_buf, iq_matrix_buf;
+    VAPictureParameterBufferMPEG2 pic_param;
+    VAIQMatrixBufferMPEG2 iq_matrix;
+
+    memset(&pic_param, 0, sizeof(pic_param));
+    vs = mpeg2_translate_reference_frames(dstSurfData, decoder, decoderData, &pic_param, vdppi);
+    if (VDP_STATUS_OK != vs) {
+        if (VDP_STATUS_RESOURCES == vs) {
+            traceError("error (%s): no surfaces left in buffer\n", __func__);
+            err_code = VDP_STATUS_RESOURCES;
+        } else {
+            err_code = VDP_STATUS_ERROR;
+        }
+        goto quit;
+    }
+
+    mpeg2_translate_pic_param(&pic_param, decoderData->width, decoderData->height, vdppi);
+    mpeg2_translate_iq_matrix(&iq_matrix, vdppi);
+
+    glx_ctx_lock();
+    status = vaCreateBuffer(va_dpy, decoderData->context_id, VAPictureParameterBufferType,
+        sizeof(VAPictureParameterBufferMPEG2), 1, &pic_param, &pic_param_buf);
+    if (VA_STATUS_SUCCESS != status) {
+        glx_ctx_unlock();
+        err_code = VDP_STATUS_ERROR;
+        goto quit;
+    }
+
+    status = vaCreateBuffer(va_dpy, decoderData->context_id, VAIQMatrixBufferType,
+        sizeof(VAIQMatrixBufferMPEG2), 1, &iq_matrix, &iq_matrix_buf);
+    if (VA_STATUS_SUCCESS != status) {
+        glx_ctx_unlock();
+        err_code = VDP_STATUS_ERROR;
+        goto quit;
+    }
+
+    // send data to decoding hardware
+    status = vaBeginPicture(va_dpy, decoderData->context_id, dstSurfData->va_surf);
+    if (VA_STATUS_SUCCESS != status) {
+        glx_ctx_unlock();
+        err_code = VDP_STATUS_ERROR;
+        goto quit;
+    }
+    status = vaRenderPicture(va_dpy, decoderData->context_id, &pic_param_buf, 1);
+    if (VA_STATUS_SUCCESS != status) {
+        glx_ctx_unlock();
+        err_code = VDP_STATUS_ERROR;
+        goto quit;
+    }
+    status = vaRenderPicture(va_dpy, decoderData->context_id, &iq_matrix_buf, 1);
+    if (VA_STATUS_SUCCESS != status) {
+        glx_ctx_unlock();
+        err_code = VDP_STATUS_ERROR;
+        goto quit;
+    }
+
+    vaDestroyBuffer(va_dpy, pic_param_buf);
+    vaDestroyBuffer(va_dpy, iq_matrix_buf);
+    glx_ctx_unlock();
+
+    // merge bitstream buffers
+    int total_bitstream_bytes = 0;
+    for (unsigned int k = 0; k < bitstream_buffer_count; k ++)
+        total_bitstream_bytes += bitstream_buffers[k].bitstream_bytes;
+
+    merged_bitstream = malloc(total_bitstream_bytes);
+    if (NULL == merged_bitstream) {
+        err_code = VDP_STATUS_RESOURCES;
+        goto quit;
+    }
+
+    do {
+        unsigned char *ptr = merged_bitstream;
+        for (unsigned int k = 0; k < bitstream_buffer_count; k ++) {
+            memcpy(ptr, bitstream_buffers[k].bitstream, bitstream_buffers[k].bitstream_bytes);
+            ptr += bitstream_buffers[k].bitstream_bytes;
+        }
+    } while(0);
+
+    // Slice parameters
+
+    // All slice data have been merged into one continuous buffer. But we must supply
+    // slices one by one to the hardware decoder, so we need to delimit them. VDPAU
+    // requires bitstream buffers to include slice start code (0x00 0x00 0x01). Those
+    // will be used to calculate offsets and sizes of slice data in code below.
+
+    rbsp_state_t st_g;      // reference, global state
+    rbsp_attach_buffer(&st_g, merged_bitstream, total_bitstream_bytes);
+    int nal_offset = rbsp_navigate_to_nal_unit(&st_g);
+    if (nal_offset < 0) {
+        traceError("error (%s): no NAL header\n", __func__);
+        err_code = VDP_STATUS_ERROR;
+        goto quit;
+    }
+
+    do {
+        VASliceParameterBufferMPEG2 sp_mpeg2;
+        memset(&sp_mpeg2, 0, sizeof(VASliceParameterBufferMPEG2));
+
+        // make a copy of global rbsp state for using in slice header parser
+        rbsp_state_t st = rbsp_copy_state(&st_g);
+        rbsp_reset_bit_counter(&st);
+        int nal_offset_next = rbsp_navigate_to_nal_unit(&st_g);
+
+        // calculate end of current slice. Note (-3). It's slice start code length.
+        const unsigned int end_pos = (nal_offset_next > 0) ? (nal_offset_next - 3)
+                                                           : total_bitstream_bytes;
+        sp_mpeg2.slice_data_size     = end_pos - nal_offset;
+        sp_mpeg2.slice_data_offset   = 0;
+        sp_mpeg2.slice_data_flag     = VA_SLICE_DATA_FLAG_ALL;
+
+	unsigned int vpos, vpos2 = 0;
+	int qscale, intra_slice_flag, intra_slice = 0;
+
+	vpos = rbsp_get_u(&st, 8); /* slice_vertical_position */
+	if (decoderData->height > 2800) 
+	  vpos2 = rbsp_get_u(&st, 3); /* optional slice_vertical_position_ext */
+
+	/* FIXME */
+	/* if sequence_scalable_extension present */
+	/*  if scalable_mode == 'data partitioning' */
+	/*   priority_breakpoint, 7 bits */
+
+	qscale = rbsp_get_u(&st, 5); /* quantiser_scale_code */
+	intra_slice_flag = rbsp_get_u(&st, 1);
+	if (1 == intra_slice_flag) {
+	  intra_slice = rbsp_get_u(&st, 1);
+	  rbsp_get_u(&st, 7);	/* reserved_bits */
+	  while (1 == rbsp_get_u(&st, 1))
+	    rbsp_get_u(&st, 8);	/* extra_information_slice */
+	}
+
+	sp_mpeg2.macroblock_offset = st.bits_eaten;
+	sp_mpeg2.slice_horizontal_position = 0;
+	sp_mpeg2.slice_vertical_position = (vpos2 << 7) + vpos -1;
+	sp_mpeg2.quantiser_scale_code = qscale;
+	sp_mpeg2.intra_slice_flag = intra_slice;
+
+        VABufferID slice_parameters_buf;
+        glx_ctx_lock();
+        status = vaCreateBuffer(va_dpy, decoderData->context_id, VASliceParameterBufferType,
+            sizeof(VASliceParameterBufferMPEG2), 1, &sp_mpeg2, &slice_parameters_buf);
+        if (VA_STATUS_SUCCESS != status) {
+            glx_ctx_unlock();
+            err_code = VDP_STATUS_ERROR;
+            goto quit;
+        }
+        status = vaRenderPicture(va_dpy, decoderData->context_id, &slice_parameters_buf, 1);
+        if (VA_STATUS_SUCCESS != status) {
+            glx_ctx_unlock();
+            err_code = VDP_STATUS_ERROR;
+            goto quit;
+        }
+
+        VABufferID slice_buf;
+        status = vaCreateBuffer(va_dpy, decoderData->context_id, VASliceDataBufferType,
+            sp_mpeg2.slice_data_size, 1, merged_bitstream + nal_offset, &slice_buf);
+        if (VA_STATUS_SUCCESS != status) {
+            glx_ctx_unlock();
+            err_code = VDP_STATUS_ERROR;
+            goto quit;
+        }
+
+        status = vaRenderPicture(va_dpy, decoderData->context_id, &slice_buf, 1);
+        if (VA_STATUS_SUCCESS != status) {
+            glx_ctx_unlock();
+            err_code = VDP_STATUS_ERROR;
+            goto quit;
+        }
+
+        vaDestroyBuffer(va_dpy, slice_parameters_buf);
+        vaDestroyBuffer(va_dpy, slice_buf);
+        glx_ctx_unlock();
+
+        if (nal_offset_next < 0)        // nal_offset_next equals -1 when there is no slice
+            break;                      // start code found. Thus that was the final slice.
+        nal_offset = nal_offset_next;
+    } while (1);
+
+    glx_ctx_lock();
+    status = vaEndPicture(va_dpy, decoderData->context_id);
+    glx_ctx_unlock();
+    if (VA_STATUS_SUCCESS != status) {
+        err_code = VDP_STATUS_ERROR;
+        goto quit;
+    }
+
+    dstSurfData->sync_va_to_glx = 1;
+    err_code = VDP_STATUS_OK;
+
+quit:
+    if (NULL != merged_bitstream)
+      free(merged_bitstream);
+
+    return err_code;
+}
+
+static
 void
 h264_translate_pic_param(VAPictureParameterBufferH264 *pic_param, uint32_t width, uint32_t height,
                          const VdpPictureInfoH264 *vdppi, uint32_t level)
@@ -673,7 +1021,14 @@ vdpDecoderRender(VdpDecoder decoder, VdpVideoSurface target,
         goto quit;
     }
 
-    if (VDP_DECODER_PROFILE_H264_BASELINE == decoderData->profile ||
+    if (VDP_DECODER_PROFILE_MPEG2_SIMPLE == decoderData->profile ||
+        VDP_DECODER_PROFILE_MPEG2_MAIN ==   decoderData->profile)
+    {
+        // TODO: check exit code
+        vdpDecoderRender_mpeg2(decoder, decoderData, dstSurfData, picture_info,
+                                  bitstream_buffer_count, bitstream_buffers);
+    }
+    else if (VDP_DECODER_PROFILE_H264_BASELINE == decoderData->profile ||
         VDP_DECODER_PROFILE_H264_MAIN ==     decoderData->profile ||
         VDP_DECODER_PROFILE_H264_HIGH ==     decoderData->profile)
     {
diff --git a/src/api.h b/src/api.h
index 79d1b2e..94fd16e 100644
--- a/src/api.h
+++ b/src/api.h
@@ -19,6 +19,7 @@
 #define DESCRIBE(xparam, format)    fprintf(stderr, #xparam " = %" #format "\n", xparam)
 
 #define MAX_RENDER_TARGETS          21
+#define NUM_RENDER_TARGETS_MPEG2    21
 #define NUM_RENDER_TARGETS_H264     21
 
 #define VDP_GENERIC_HANDLE_FIELDS                   \
