frontends/va: handle protected slice data buffer
authorBoyuan Zhang <boyuan.zhang@amd.com>
Thu, 14 May 2020 01:27:45 +0000 (21:27 -0400)
committerPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Wed, 4 Nov 2020 08:21:36 +0000 (09:21 +0100)
Add a function to handle VaProtectedSliceDataBuffer, which is used for
sending decryption parameters. Also, for protected playback, there is
no need to check start code since data is encrypted.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7006>

src/gallium/frontends/va/picture.c

index bd687c8..4706013 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "util/u_handle_table.h"
 #include "util/u_video.h"
+#include "util/u_memory.h"
 
 #include "vl/vl_vlc.h"
 #include "vl/vl_winsys.h"
@@ -262,6 +263,18 @@ bufHasStartcode(vlVaBuffer *buf, unsigned int code, unsigned int bits)
 }
 
 static void
+handleVAProtectedSliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
+{
+       uint8_t* encrypted_data = (uint8_t*) buf->data;
+
+       unsigned int drm_key_size = 56 * 4;
+
+       context->desc.base.decrypt_key = CALLOC(1, drm_key_size);
+       memcpy(context->desc.base.decrypt_key, encrypted_data, drm_key_size);
+       context->desc.base.protected_playback = true;
+}
+
+static void
 handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
 {
    enum pipe_video_format format;
@@ -274,50 +287,52 @@ handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
    static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 };
 
    format = u_reduce_video_profile(context->templat.profile);
-   switch (format) {
-   case PIPE_VIDEO_FORMAT_MPEG4_AVC:
-      if (bufHasStartcode(buf, 0x000001, 24))
+   if (!context->desc.base.protected_playback) {
+      switch (format) {
+      case PIPE_VIDEO_FORMAT_MPEG4_AVC:
+         if (bufHasStartcode(buf, 0x000001, 24))
+            break;
+
+         buffers[num_buffers] = (void *const)&start_code_h264;
+         sizes[num_buffers++] = sizeof(start_code_h264);
          break;
+      case PIPE_VIDEO_FORMAT_HEVC:
+         if (bufHasStartcode(buf, 0x000001, 24))
+            break;
 
-      buffers[num_buffers] = (void *const)&start_code_h264;
-      sizes[num_buffers++] = sizeof(start_code_h264);
-      break;
-   case PIPE_VIDEO_FORMAT_HEVC:
-      if (bufHasStartcode(buf, 0x000001, 24))
+         buffers[num_buffers] = (void *const)&start_code_h265;
+         sizes[num_buffers++] = sizeof(start_code_h265);
          break;
-
-      buffers[num_buffers] = (void *const)&start_code_h265;
-      sizes[num_buffers++] = sizeof(start_code_h265);
-      break;
-   case PIPE_VIDEO_FORMAT_VC1:
-      if (bufHasStartcode(buf, 0x0000010d, 32) ||
-          bufHasStartcode(buf, 0x0000010c, 32) ||
-          bufHasStartcode(buf, 0x0000010b, 32))
+      case PIPE_VIDEO_FORMAT_VC1:
+         if (bufHasStartcode(buf, 0x0000010d, 32) ||
+             bufHasStartcode(buf, 0x0000010c, 32) ||
+             bufHasStartcode(buf, 0x0000010b, 32))
+            break;
+
+         if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) {
+            buffers[num_buffers] = (void *const)&start_code_vc1;
+            sizes[num_buffers++] = sizeof(start_code_vc1);
+         }
          break;
+      case PIPE_VIDEO_FORMAT_MPEG4:
+         if (bufHasStartcode(buf, 0x000001, 24))
+            break;
 
-      if (context->decoder->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) {
-         buffers[num_buffers] = (void *const)&start_code_vc1;
-         sizes[num_buffers++] = sizeof(start_code_vc1);
-      }
-      break;
-   case PIPE_VIDEO_FORMAT_MPEG4:
-      if (bufHasStartcode(buf, 0x000001, 24))
+         vlVaDecoderFixMPEG4Startcode(context);
+         buffers[num_buffers] = (void *)context->mpeg4.start_code;
+         sizes[num_buffers++] = context->mpeg4.start_code_size;
          break;
-
-      vlVaDecoderFixMPEG4Startcode(context);
-      buffers[num_buffers] = (void *)context->mpeg4.start_code;
-      sizes[num_buffers++] = context->mpeg4.start_code_size;
-      break;
-   case PIPE_VIDEO_FORMAT_JPEG:
-      vlVaGetJpegSliceHeader(context);
-      buffers[num_buffers] = (void *)context->mjpeg.slice_header;
-      sizes[num_buffers++] = context->mjpeg.slice_header_size;
-      break;
-   case PIPE_VIDEO_FORMAT_VP9:
-      vlVaDecoderVP9BitstreamHeader(context, buf);
-      break;
-   default:
-      break;
+      case PIPE_VIDEO_FORMAT_JPEG:
+         vlVaGetJpegSliceHeader(context);
+         buffers[num_buffers] = (void *)context->mjpeg.slice_header;
+         sizes[num_buffers++] = context->mjpeg.slice_header_size;
+         break;
+      case PIPE_VIDEO_FORMAT_VP9:
+         vlVaDecoderVP9BitstreamHeader(context, buf);
+         break;
+      default:
+         break;
+      }
    }
 
    buffers[num_buffers] = buf->data;
@@ -531,6 +546,7 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff
       return VA_STATUS_ERROR_INVALID_CONTEXT;
    }
 
+   /* Always process VAProtectedSliceDataBufferType first because it changes the state */
    for (i = 0; i < num_buffers; ++i) {
       vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]);
       if (!buf) {
@@ -538,6 +554,13 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff
          return VA_STATUS_ERROR_INVALID_BUFFER;
       }
 
+      if (buf->type == VAProtectedSliceDataBufferType)
+         handleVAProtectedSliceDataBufferType(context, buf);
+   }
+
+   for (i = 0; i < num_buffers; ++i) {
+      vlVaBuffer *buf = handle_table_get(drv->htab, buffers[i]);
+
       switch (buf->type) {
       case VAPictureParameterBufferType:
          vaStatus = handlePictureParameterBuffer(drv, context, buf);
@@ -554,6 +577,7 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff
       case VASliceDataBufferType:
          handleVASliceDataBufferType(context, buf);
          break;
+
       case VAProcPipelineParameterBufferType:
          vaStatus = vlVaHandleVAProcPipelineParameterBufferType(drv, context, buf);
          break;