~ubuntu-branches/ubuntu/utopic/gst-plugins-bad1.0/utopic

« back to all changes in this revision

Viewing changes to sys/androidmedia/gstamcvideodechybris.c

  • Committer: Package Import Robot
  • Author(s): Ricardo Salveti de Araujo
  • Date: 2013-10-13 00:30:29 UTC
  • Revision ID: package-import@ubuntu.com-20131013003029-e948f02g1aq3go50
Tags: 1.2.0-3ubuntu3
* Refreshing adding-mirsink-and-android-media-over-hybris-support.patch:
  - Adding support for software rendering
  - Better input/out buffer handling
* debian/build-deps.in:
  - Bumping dep version requirement for libmedia

Show diffs side-by-side

added added

removed removed

Lines of Context:
500
500
 
501
501
  g_mutex_init (&self->drain_lock);
502
502
  g_cond_init (&self->drain_cond);
503
 
 
504
 
  self->dec_format = NULL;
505
503
}
506
504
 
507
505
static gboolean
549
547
{
550
548
  GstAmcVideoDec *self = GST_AMC_VIDEO_DEC (object);
551
549
 
552
 
  gst_amc_format_free (self->dec_format);
553
 
 
554
550
  g_mutex_clear (&self->drain_lock);
555
551
  g_cond_clear (&self->drain_cond);
556
552
 
817
813
      gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self));
818
814
  GstVideoInfo *info = &state->info;
819
815
  gboolean ret = FALSE;
 
816
  GstMemory *mem = { NULL };
 
817
  gboolean do_hardware_rendering = FALSE;
820
818
  gint err = 0;
821
819
 
822
820
  GST_DEBUG_OBJECT (self, "%s", __PRETTY_FUNCTION__);
837
835
      "buffer_info->size: %d, gst_buffer_get_size (outbuf): %d",
838
836
      buffer_info->size, gst_buffer_get_size (outbuf));
839
837
 
 
838
  if (gst_buffer_n_memory (outbuf) >= 1 &&
 
839
      (mem = gst_buffer_peek_memory (outbuf, 0))
 
840
      && gst_is_mir_image_memory (mem)) {
 
841
 
 
842
    GST_DEBUG_OBJECT (self, "It is Mir image memory");
 
843
    do_hardware_rendering = gst_mir_do_hardware_render (mem);
 
844
  }
 
845
 
 
846
  GST_DEBUG_OBJECT (self, "hardware_rendering: %d", do_hardware_rendering);
 
847
 
840
848
  /* Same video format */
841
 
  if (buffer_info->size == 0 && gst_buffer_get_size (outbuf) > 0) {
842
 
    GstMemory *mem = { NULL };
843
 
    GST_DEBUG_OBJECT (self, "Doing hardware rendering");
844
 
 
845
 
    if (gst_buffer_n_memory (outbuf) >= 1 &&
846
 
        (mem = gst_buffer_peek_memory (outbuf, 0))
847
 
        && gst_is_mir_image_memory (mem)) {
848
 
 
849
 
      GST_DEBUG_OBJECT (self, "It is Mir image memory");
 
849
  if (do_hardware_rendering
 
850
      && buffer_info->size == 0 && gst_buffer_get_size (outbuf) > 0) {
 
851
 
 
852
    if (gst_buffer_n_memory (outbuf) >= 1 && gst_is_mir_image_memory (mem)) {
 
853
      GST_DEBUG_OBJECT (self, "Doing hardware rendering");
850
854
      GST_DEBUG_OBJECT (self, "gst_mir_image_memory_get_codec: %p",
851
855
          self->codec->codec_delegate);
852
 
    } else if (buffer_info->size == gst_buffer_get_size (outbuf)) {
853
 
      GstMapInfo minfo;
854
 
      GST_DEBUG_OBJECT (self, "Doing fast software rendering");
855
856
 
856
 
      gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
857
 
      orc_memcpy (minfo.data, buf->data + buffer_info->offset,
858
 
          buffer_info->size);
859
 
      gst_buffer_unmap (outbuf, &minfo);
 
857
      ret = TRUE;
 
858
      goto done;
860
859
    }
 
860
  } else if (!do_hardware_rendering
 
861
      && buffer_info->size == gst_buffer_get_size (outbuf)) {
 
862
    GstMapInfo minfo;
 
863
    GST_DEBUG_OBJECT (self, "Doing fast software rendering");
 
864
 
 
865
    gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
 
866
    orc_memcpy (minfo.data, buf->data + buffer_info->offset, buffer_info->size);
 
867
    gst_buffer_unmap (outbuf, &minfo);
 
868
 
861
869
    ret = TRUE;
862
 
    goto done;
863
 
  }
864
 
 
865
 
  /* Disabled for now since this plugin does not support non-hardware accelerated
866
 
   * video rendering at the moment.
867
 
   */
868
 
  GST_DEBUG_OBJECT (self, "Doing slow software line-by-line copying");
869
 
 
870
 
  /* Different video format, try to convert */
871
 
  switch (self->color_format) {
872
 
    case COLOR_FormatYUV420Planar:{
873
 
      GstVideoFrame vframe;
874
 
      gint i, j, height;
875
 
      guint8 *src, *dest;
876
 
      gint stride, slice_height;
877
 
      gint src_stride, dest_stride;
878
 
      gint row_length;
879
 
 
880
 
      stride = self->stride;
881
 
      if (stride == 0) {
882
 
        GST_ERROR_OBJECT (self, "Stride not set");
883
 
        goto done;
884
 
      }
885
 
 
886
 
      slice_height = self->slice_height;
887
 
      if (slice_height == 0) {
888
 
        /* NVidia Tegra 3 on Nexus 7 does not set this */
889
 
        if (g_str_has_prefix (klass->codec_info->name, "OMX.Nvidia.")) {
890
 
          slice_height = GST_ROUND_UP_32 (self->height);
891
 
        } else {
892
 
          GST_ERROR_OBJECT (self, "Slice height not set");
893
 
          goto done;
894
 
        }
895
 
      }
896
 
 
897
 
      gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
898
 
      for (i = 0; i < 3; i++) {
899
 
        if (i == 0) {
900
 
          src_stride = stride;
901
 
          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
902
 
        } else {
903
 
          src_stride = (stride + 1) / 2;
904
 
          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
905
 
        }
906
 
 
907
 
        src = buf->data + buffer_info->offset;
908
 
 
909
 
        if (i == 0) {
910
 
          src += self->crop_top * stride;
911
 
          src += self->crop_left;
912
 
          row_length = self->width;
913
 
        } else if (i > 0) {
914
 
          /* skip the Y plane */
915
 
          src += slice_height * stride;
916
 
 
917
 
          /* crop_top/crop_left divided by two
918
 
           * because one byte of the U/V planes
919
 
           * corresponds to two pixels horizontally/vertically */
920
 
          src += self->crop_top / 2 * src_stride;
921
 
          src += self->crop_left / 2;
922
 
          row_length = (self->width + 1) / 2;
923
 
        }
924
 
        if (i == 2) {
925
 
          /* skip the U plane */
926
 
          src += ((slice_height + 1) / 2) * ((stride + 1) / 2);
927
 
        }
928
 
 
929
 
        dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
930
 
        height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
931
 
 
932
 
        for (j = 0; j < height; j++) {
933
 
          orc_memcpy (dest, src, row_length);
934
 
          src += src_stride;
935
 
          dest += dest_stride;
936
 
        }
937
 
      }
938
 
      gst_video_frame_unmap (&vframe);
939
 
      ret = TRUE;
940
 
      break;
941
 
    }
942
 
    case COLOR_TI_FormatYUV420PackedSemiPlanar:
943
 
    case COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced:{
944
 
      gint i, j, height;
945
 
      guint8 *src, *dest;
946
 
      gint src_stride, dest_stride;
947
 
      gint row_length;
948
 
      GstVideoFrame vframe;
949
 
 
950
 
      /* This should always be set */
951
 
      if (self->stride == 0 || self->slice_height == 0) {
952
 
        GST_ERROR_OBJECT (self, "Stride or slice height not set");
953
 
        goto done;
954
 
      }
955
 
 
956
 
      /* FIXME: This does not work for odd widths or heights
957
 
       * but might as well be a bug in the codec */
958
 
      gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
959
 
      for (i = 0; i < 2; i++) {
960
 
        if (i == 0) {
961
 
          src_stride = self->stride;
962
 
          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
963
 
        } else {
964
 
          src_stride = GST_ROUND_UP_2 (self->stride);
965
 
          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
966
 
        }
967
 
 
968
 
        src = buf->data + buffer_info->offset;
969
 
        if (i == 0) {
970
 
          row_length = self->width;
971
 
        } else if (i == 1) {
972
 
          src += (self->slice_height - self->crop_top / 2) * self->stride;
973
 
          row_length = GST_ROUND_UP_2 (self->width);
974
 
        }
975
 
 
976
 
        dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
977
 
        height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
978
 
 
979
 
        for (j = 0; j < height; j++) {
980
 
          orc_memcpy (dest, src, row_length);
981
 
          src += src_stride;
982
 
          dest += dest_stride;
983
 
        }
984
 
      }
985
 
      gst_video_frame_unmap (&vframe);
986
 
      ret = TRUE;
987
 
      break;
988
 
    }
989
 
    case COLOR_QCOM_FormatYUV420SemiPlanar:
990
 
    case COLOR_FormatYUV420SemiPlanar:{
991
 
      gint i, j, height;
992
 
      guint8 *src, *dest;
993
 
      gint src_stride, dest_stride, fixed_stride;
994
 
      gint row_length;
995
 
      GstVideoFrame vframe;
996
 
 
997
 
      /* This should always be set */
998
 
      if (self->stride == 0 || self->slice_height == 0) {
999
 
        GST_ERROR_OBJECT (self, "Stride or slice height not set");
1000
 
        goto done;
1001
 
      }
1002
 
 
1003
 
      /* Samsung Galaxy S3 seems to report wrong strides.
1004
 
         I.e. BigBuckBunny 854x480 H264 reports a stride of 864 when it is
1005
 
         actually 854, so we use width instead of stride here.
1006
 
         This is obviously bound to break in the future. */
1007
 
      if (g_str_has_prefix (klass->codec_info->name, "OMX.SEC.")) {
1008
 
        fixed_stride = self->width;
1009
 
      } else {
1010
 
        fixed_stride = self->stride;
1011
 
      }
1012
 
 
1013
 
      gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
1014
 
 
1015
 
      for (i = 0; i < 2; i++) {
1016
 
        src_stride = fixed_stride;
1017
 
        dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
1018
 
 
1019
 
        src = buf->data + buffer_info->offset;
1020
 
        if (i == 0) {
1021
 
          src += self->crop_top * fixed_stride;
1022
 
          src += self->crop_left;
1023
 
          row_length = self->width;
1024
 
        } else if (i == 1) {
1025
 
          src += self->slice_height * fixed_stride;
1026
 
          src += self->crop_top * fixed_stride;
1027
 
          src += self->crop_left;
1028
 
          row_length = self->width;
1029
 
        }
1030
 
 
1031
 
        dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
1032
 
        height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
1033
 
 
1034
 
        for (j = 0; j < height; j++) {
1035
 
          orc_memcpy (dest, src, row_length);
1036
 
          src += src_stride;
1037
 
          dest += dest_stride;
1038
 
        }
1039
 
      }
1040
 
      gst_video_frame_unmap (&vframe);
1041
 
      ret = TRUE;
1042
 
      break;
1043
 
    }
1044
 
      /* FIXME: This should be in libgstvideo as MT12 or similar, see v4l2 */
1045
 
    case COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka:{
1046
 
      GstVideoFrame vframe;
1047
 
      gint width = self->width;
1048
 
      gint height = self->height;
1049
 
      gint dest_luma_stride, dest_chroma_stride;
1050
 
      guint8 *src = buf->data + buffer_info->offset;
1051
 
      guint8 *dest_luma, *dest_chroma;
1052
 
      gint y;
1053
 
      const size_t tile_w = (width - 1) / TILE_WIDTH + 1;
1054
 
      const size_t tile_w_align = (tile_w + 1) & ~1;
1055
 
      const size_t tile_h_luma = (height - 1) / TILE_HEIGHT + 1;
1056
 
      const size_t tile_h_chroma = (height / 2 - 1) / TILE_HEIGHT + 1;
1057
 
      size_t luma_size = tile_w_align * tile_h_luma * TILE_SIZE;
1058
 
 
1059
 
      gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
1060
 
      dest_luma = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0);
1061
 
      dest_chroma = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1);
1062
 
      dest_luma_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0);
1063
 
      dest_chroma_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 1);
1064
 
 
1065
 
      if ((luma_size % TILE_GROUP_SIZE) != 0)
1066
 
        luma_size = (((luma_size - 1) / TILE_GROUP_SIZE) + 1) * TILE_GROUP_SIZE;
1067
 
 
1068
 
      for (y = 0; y < tile_h_luma; y++) {
1069
 
        size_t row_width = width;
1070
 
        gint x;
1071
 
 
1072
 
        for (x = 0; x < tile_w; x++) {
1073
 
          size_t tile_width = row_width;
1074
 
          size_t tile_height = height;
1075
 
          gint luma_idx;
1076
 
          gint chroma_idx;
1077
 
          /* luma source pointer for this tile */
1078
 
          const uint8_t *src_luma = src
1079
 
              + tile_pos (x, y, tile_w_align, tile_h_luma) * TILE_SIZE;
1080
 
 
1081
 
          /* chroma source pointer for this tile */
1082
 
          const uint8_t *src_chroma = src + luma_size
1083
 
              + tile_pos (x, y / 2, tile_w_align, tile_h_chroma) * TILE_SIZE;
1084
 
          if (y & 1)
1085
 
            src_chroma += TILE_SIZE / 2;
1086
 
 
1087
 
          /* account for right columns */
1088
 
          if (tile_width > TILE_WIDTH)
1089
 
            tile_width = TILE_WIDTH;
1090
 
 
1091
 
          /* account for bottom rows */
1092
 
          if (tile_height > TILE_HEIGHT)
1093
 
            tile_height = TILE_HEIGHT;
1094
 
 
1095
 
          /* dest luma memory index for this tile */
1096
 
          luma_idx = y * TILE_HEIGHT * dest_luma_stride + x * TILE_WIDTH;
1097
 
 
1098
 
          /* dest chroma memory index for this tile */
1099
 
          /* XXX: remove divisions */
1100
 
          chroma_idx =
1101
 
              y * TILE_HEIGHT / 2 * dest_chroma_stride + x * TILE_WIDTH;
1102
 
 
1103
 
          tile_height /= 2;     // we copy 2 luma lines at once
1104
 
          while (tile_height--) {
1105
 
            memcpy (dest_luma + luma_idx, src_luma, tile_width);
1106
 
            src_luma += TILE_WIDTH;
1107
 
            luma_idx += dest_luma_stride;
1108
 
 
1109
 
            memcpy (dest_luma + luma_idx, src_luma, tile_width);
1110
 
            src_luma += TILE_WIDTH;
1111
 
            luma_idx += dest_luma_stride;
1112
 
 
1113
 
            memcpy (dest_chroma + chroma_idx, src_chroma, tile_width);
1114
 
            src_chroma += TILE_WIDTH;
1115
 
            chroma_idx += dest_chroma_stride;
1116
 
          }
1117
 
          row_width -= TILE_WIDTH;
1118
 
        }
1119
 
        height -= TILE_HEIGHT;
1120
 
      }
1121
 
      gst_video_frame_unmap (&vframe);
1122
 
      ret = TRUE;
1123
 
      break;
1124
 
 
1125
 
    }
1126
 
    default:
1127
 
      GST_ERROR_OBJECT (self, "Unsupported color format %d",
1128
 
          self->color_format);
1129
 
      goto done;
1130
 
      break;
1131
 
  }
1132
 
 
1133
 
  /* Render and release the output buffer back to the decoder */
1134
 
  err = media_codec_release_output_buffer (self->codec->codec_delegate, 0);
 
870
  } else {
 
871
    /* Disabled for now since this plugin does not support non-hardware accelerated
 
872
     * video rendering at the moment.
 
873
     */
 
874
    GST_DEBUG_OBJECT (self,
 
875
        "Doing slow software line-by-line copying with format conversion");
 
876
 
 
877
    /* Different video format, try to convert */
 
878
    switch (self->color_format) {
 
879
      case COLOR_FormatYUV420Planar:{
 
880
        GstVideoFrame vframe;
 
881
        gint i, j, height;
 
882
        guint8 *src, *dest;
 
883
        gint stride, slice_height;
 
884
        gint src_stride, dest_stride;
 
885
        gint row_length;
 
886
 
 
887
        stride = self->stride;
 
888
        if (stride == 0) {
 
889
          GST_ERROR_OBJECT (self, "Stride not set");
 
890
          goto done;
 
891
        }
 
892
 
 
893
        slice_height = self->slice_height;
 
894
        if (slice_height == 0) {
 
895
          /* NVidia Tegra 3 on Nexus 7 does not set this */
 
896
          if (g_str_has_prefix (klass->codec_info->name, "OMX.Nvidia.")) {
 
897
            slice_height = GST_ROUND_UP_32 (self->height);
 
898
          } else {
 
899
            GST_ERROR_OBJECT (self, "Slice height not set");
 
900
            goto done;
 
901
          }
 
902
        }
 
903
 
 
904
        gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
 
905
        for (i = 0; i < 3; i++) {
 
906
          if (i == 0) {
 
907
            src_stride = stride;
 
908
            dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
 
909
          } else {
 
910
            src_stride = (stride + 1) / 2;
 
911
            dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
 
912
          }
 
913
 
 
914
          src = buf->data + buffer_info->offset;
 
915
 
 
916
          if (i == 0) {
 
917
            src += self->crop_top * stride;
 
918
            src += self->crop_left;
 
919
            row_length = self->width;
 
920
          } else if (i > 0) {
 
921
            /* skip the Y plane */
 
922
            src += slice_height * stride;
 
923
 
 
924
            /* crop_top/crop_left divided by two
 
925
             * because one byte of the U/V planes
 
926
             * corresponds to two pixels horizontally/vertically */
 
927
            src += self->crop_top / 2 * src_stride;
 
928
            src += self->crop_left / 2;
 
929
            row_length = (self->width + 1) / 2;
 
930
          }
 
931
          if (i == 2) {
 
932
            /* skip the U plane */
 
933
            src += ((slice_height + 1) / 2) * ((stride + 1) / 2);
 
934
          }
 
935
 
 
936
          dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
 
937
          height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
 
938
 
 
939
          for (j = 0; j < height; j++) {
 
940
            orc_memcpy (dest, src, row_length);
 
941
            src += src_stride;
 
942
            dest += dest_stride;
 
943
          }
 
944
        }
 
945
        gst_video_frame_unmap (&vframe);
 
946
        ret = TRUE;
 
947
        break;
 
948
      }
 
949
      case COLOR_TI_COLOR_FormatYUV420PackedSemiPlanar:
 
950
      case COLOR_TI_FormatYUV420PackedSemiPlanar:
 
951
      case COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced:{
 
952
        gint i, j, height;
 
953
        guint8 *src, *dest;
 
954
        gint src_stride, dest_stride;
 
955
        gint row_length;
 
956
        GstVideoFrame vframe;
 
957
 
 
958
        GST_DEBUG_OBJECT (self,
 
959
            "COLOR_TI_COLOR_FormatYUV420PackedSemiPlanar conversion");
 
960
 
 
961
        /* This should always be set */
 
962
        if (self->stride == 0 || self->slice_height == 0) {
 
963
          GST_ERROR_OBJECT (self, "Stride or slice height not set");
 
964
          goto done;
 
965
        }
 
966
 
 
967
        /* FIXME: This does not work for odd widths or heights
 
968
         * but might as well be a bug in the codec */
 
969
        gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
 
970
        for (i = 0; i < 2; i++) {
 
971
          if (i == 0) {
 
972
            src_stride = self->stride;
 
973
            dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
 
974
          } else {
 
975
            src_stride = GST_ROUND_UP_2 (self->stride);
 
976
            dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
 
977
          }
 
978
 
 
979
          src = buf->data + buffer_info->offset;
 
980
#if 0
 
981
          GST_DEBUG_OBJECT (self, "buf->data: %p, buffer_info->offset: %d",
 
982
              buf->data, buffer_info->offset);
 
983
          GST_DEBUG_OBJECT (self, "buf->size: %d", buf->size);
 
984
#endif
 
985
          if (i == 0) {
 
986
            row_length = self->width;
 
987
          } else if (i == 1) {
 
988
            src += (self->slice_height - self->crop_top / 2) * self->stride;
 
989
            row_length = GST_ROUND_UP_2 (self->width);
 
990
          }
 
991
 
 
992
          dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
 
993
          height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
 
994
 
 
995
          for (j = 0; j < height; j++) {
 
996
#if 0
 
997
            GST_DEBUG_OBJECT (self,
 
998
                "Copying data row (dest: %p, src: %p, row_length: %d", dest,
 
999
                src, row_length);
 
1000
#endif
 
1001
            orc_memcpy (dest, src, row_length);
 
1002
            src += src_stride;
 
1003
            dest += dest_stride;
 
1004
#if 0
 
1005
            GST_DEBUG_OBJECT (self,
 
1006
                "Finished copying data row (src_stride: %d, dst_stride: %d",
 
1007
                src_stride, dest_stride);
 
1008
#endif
 
1009
          }
 
1010
        }
 
1011
        gst_video_frame_unmap (&vframe);
 
1012
        ret = TRUE;
 
1013
        break;
 
1014
      }
 
1015
      case COLOR_QCOM_FormatYUV420SemiPlanar:
 
1016
      case COLOR_FormatYUV420SemiPlanar:{
 
1017
        gint i, j, height;
 
1018
        guint8 *src, *dest;
 
1019
        gint src_stride, dest_stride, fixed_stride;
 
1020
        gint row_length;
 
1021
        GstVideoFrame vframe;
 
1022
 
 
1023
        /* This should always be set */
 
1024
        if (self->stride == 0 || self->slice_height == 0) {
 
1025
          GST_ERROR_OBJECT (self, "Stride or slice height not set");
 
1026
          goto done;
 
1027
        }
 
1028
 
 
1029
        /* Samsung Galaxy S3 seems to report wrong strides.
 
1030
           I.e. BigBuckBunny 854x480 H264 reports a stride of 864 when it is
 
1031
           actually 854, so we use width instead of stride here.
 
1032
           This is obviously bound to break in the future. */
 
1033
        if (g_str_has_prefix (klass->codec_info->name, "OMX.SEC.")) {
 
1034
          fixed_stride = self->width;
 
1035
        } else {
 
1036
          fixed_stride = self->stride;
 
1037
        }
 
1038
 
 
1039
        gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
 
1040
 
 
1041
        for (i = 0; i < 2; i++) {
 
1042
          src_stride = fixed_stride;
 
1043
          dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
 
1044
 
 
1045
          src = buf->data + buffer_info->offset;
 
1046
          if (i == 0) {
 
1047
            src += self->crop_top * fixed_stride;
 
1048
            src += self->crop_left;
 
1049
            row_length = self->width;
 
1050
          } else if (i == 1) {
 
1051
            src += self->slice_height * fixed_stride;
 
1052
            src += self->crop_top * fixed_stride;
 
1053
            src += self->crop_left;
 
1054
            row_length = self->width;
 
1055
          }
 
1056
 
 
1057
          dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
 
1058
          height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
 
1059
 
 
1060
          for (j = 0; j < height; j++) {
 
1061
            orc_memcpy (dest, src, row_length);
 
1062
            src += src_stride;
 
1063
            dest += dest_stride;
 
1064
          }
 
1065
        }
 
1066
        gst_video_frame_unmap (&vframe);
 
1067
        ret = TRUE;
 
1068
        break;
 
1069
      }
 
1070
        /* FIXME: This should be in libgstvideo as MT12 or similar, see v4l2 */
 
1071
      case COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka:{
 
1072
        GstVideoFrame vframe;
 
1073
        gint width = self->width;
 
1074
        gint height = self->height;
 
1075
        gint dest_luma_stride, dest_chroma_stride;
 
1076
        guint8 *src = buf->data + buffer_info->offset;
 
1077
        guint8 *dest_luma, *dest_chroma;
 
1078
        gint y;
 
1079
        const size_t tile_w = (width - 1) / TILE_WIDTH + 1;
 
1080
        const size_t tile_w_align = (tile_w + 1) & ~1;
 
1081
        const size_t tile_h_luma = (height - 1) / TILE_HEIGHT + 1;
 
1082
        const size_t tile_h_chroma = (height / 2 - 1) / TILE_HEIGHT + 1;
 
1083
        size_t luma_size = tile_w_align * tile_h_luma * TILE_SIZE;
 
1084
 
 
1085
        gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
 
1086
        dest_luma = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0);
 
1087
        dest_chroma = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1);
 
1088
        dest_luma_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0);
 
1089
        dest_chroma_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 1);
 
1090
 
 
1091
        if ((luma_size % TILE_GROUP_SIZE) != 0)
 
1092
          luma_size =
 
1093
              (((luma_size - 1) / TILE_GROUP_SIZE) + 1) * TILE_GROUP_SIZE;
 
1094
 
 
1095
        for (y = 0; y < tile_h_luma; y++) {
 
1096
          size_t row_width = width;
 
1097
          gint x;
 
1098
 
 
1099
          for (x = 0; x < tile_w; x++) {
 
1100
            size_t tile_width = row_width;
 
1101
            size_t tile_height = height;
 
1102
            gint luma_idx;
 
1103
            gint chroma_idx;
 
1104
            /* luma source pointer for this tile */
 
1105
            const uint8_t *src_luma = src
 
1106
                + tile_pos (x, y, tile_w_align, tile_h_luma) * TILE_SIZE;
 
1107
 
 
1108
            /* chroma source pointer for this tile */
 
1109
            const uint8_t *src_chroma = src + luma_size
 
1110
                + tile_pos (x, y / 2, tile_w_align, tile_h_chroma) * TILE_SIZE;
 
1111
            if (y & 1)
 
1112
              src_chroma += TILE_SIZE / 2;
 
1113
 
 
1114
            /* account for right columns */
 
1115
            if (tile_width > TILE_WIDTH)
 
1116
              tile_width = TILE_WIDTH;
 
1117
 
 
1118
            /* account for bottom rows */
 
1119
            if (tile_height > TILE_HEIGHT)
 
1120
              tile_height = TILE_HEIGHT;
 
1121
 
 
1122
            /* dest luma memory index for this tile */
 
1123
            luma_idx = y * TILE_HEIGHT * dest_luma_stride + x * TILE_WIDTH;
 
1124
 
 
1125
            /* dest chroma memory index for this tile */
 
1126
            /* XXX: remove divisions */
 
1127
            chroma_idx =
 
1128
                y * TILE_HEIGHT / 2 * dest_chroma_stride + x * TILE_WIDTH;
 
1129
 
 
1130
            tile_height /= 2;   // we copy 2 luma lines at once
 
1131
            while (tile_height--) {
 
1132
              memcpy (dest_luma + luma_idx, src_luma, tile_width);
 
1133
              src_luma += TILE_WIDTH;
 
1134
              luma_idx += dest_luma_stride;
 
1135
 
 
1136
              memcpy (dest_luma + luma_idx, src_luma, tile_width);
 
1137
              src_luma += TILE_WIDTH;
 
1138
              luma_idx += dest_luma_stride;
 
1139
 
 
1140
              memcpy (dest_chroma + chroma_idx, src_chroma, tile_width);
 
1141
              src_chroma += TILE_WIDTH;
 
1142
              chroma_idx += dest_chroma_stride;
 
1143
            }
 
1144
            row_width -= TILE_WIDTH;
 
1145
          }
 
1146
          height -= TILE_HEIGHT;
 
1147
        }
 
1148
        gst_video_frame_unmap (&vframe);
 
1149
        ret = TRUE;
 
1150
        break;
 
1151
 
 
1152
      }
 
1153
      default:
 
1154
        GST_ERROR_OBJECT (self, "Unsupported color format %d",
 
1155
            self->color_format);
 
1156
        goto done;
 
1157
        break;
 
1158
    }
 
1159
  }
 
1160
 
 
1161
  /* Just release the output buffer back to the decoder */
 
1162
  err =
 
1163
      media_codec_release_output_buffer (self->codec->codec_delegate, 0, FALSE);
1135
1164
  if (err < 0)
1136
1165
    GST_WARNING_OBJECT (self,
1137
1166
        "Failed to release output buffer. Rendering will probably be affected (err: %d).",
1143
1172
}
1144
1173
 
1145
1174
static gboolean
1146
 
gst_amc_video_dec_configure_self (GstAmcVideoDec * self)
 
1175
gst_amc_video_dec_configure_self (GstVideoDecoder * decoder,
 
1176
    GstAmcFormat * format)
1147
1177
{
 
1178
  GstAmcVideoDec *self = GST_AMC_VIDEO_DEC (decoder);
 
1179
 
 
1180
  g_return_val_if_fail (decoder != NULL, FALSE);
 
1181
  g_return_val_if_fail (format != NULL, FALSE);
 
1182
 
1148
1183
  /* Configure the hardware decoder */
1149
 
  if (!gst_amc_codec_configure (self->codec, self->dec_format, NULL, 0)) {
 
1184
  if (!gst_amc_codec_configure (self->codec, format, NULL, 0)) {
1150
1185
    GST_ERROR_OBJECT (self, "Failed to configure codec");
1151
1186
    return FALSE;
1152
1187
  }
1327
1362
 
1328
1363
    if (!gst_amc_video_dec_fill_buffer (self, idx, &buffer_info, outbuf)) {
1329
1364
      gst_buffer_unref (outbuf);
1330
 
      if (!gst_amc_codec_release_output_buffer (self->codec, idx))
 
1365
      if (!gst_amc_codec_release_output_buffer (self->codec, idx, FALSE))
1331
1366
        GST_ERROR_OBJECT (self, "Failed to release output buffer index %d",
1332
1367
            idx);
1333
1368
      goto invalid_buffer;
1338
1373
        1);
1339
1374
    flow_ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf);
1340
1375
  } else if (buffer_info.size >= 0 && is_eos == FALSE) {
1341
 
    GST_DEBUG_OBJECT (self, "Should be allocating buffer from custom pool");
 
1376
    GST_DEBUG_OBJECT (self, "Allocating buffer from pool");
1342
1377
    /* Allocate buffer from the GstBufferPool */
1343
1378
    if ((flow_ret = gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER
1344
1379
                (self), frame)) != GST_FLOW_OK) {
1352
1387
            frame->output_buffer)) {
1353
1388
      gst_buffer_replace (&frame->output_buffer, NULL);
1354
1389
      gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
1355
 
      if (!gst_amc_codec_release_output_buffer (self->codec, idx))
 
1390
      if (!gst_amc_codec_release_output_buffer (self->codec, idx, FALSE))
1356
1391
        GST_ERROR_OBJECT (self, "Failed to release output buffer index %d",
1357
1392
            idx);
1358
1393
      goto invalid_buffer;
1612
1647
    GST_ERROR_OBJECT (self, "Failed to create video format");
1613
1648
    return FALSE;
1614
1649
  }
1615
 
  /* FIXME: New fix */
1616
 
  self->dec_format = format;
1617
1650
 
1618
1651
  /* FIXME: This buffer needs to be valid until the codec is stopped again */
1619
1652
  if (self->codec_data)
1627
1660
*/
1628
1661
 
1629
1662
  /* Configure the hardware codec with format */
1630
 
  ret = gst_amc_video_dec_configure_self (self);
1631
 
  GST_DEBUG_OBJECT (self, "gst_amc_video_dec_configure_self returned: %d", ret);
 
1663
  ret = gst_amc_video_dec_configure_self (decoder, format);
 
1664
  if (!ret) {
 
1665
    goto failed_configure;
 
1666
  }
1632
1667
 
1633
1668
  gst_amc_format_free (format);
 
1669
  format = NULL;
1634
1670
 
1635
1671
  self->started = TRUE;
1636
1672
  self->input_state = gst_video_codec_state_ref (state);
1642
1678
  gst_pad_start_task (GST_VIDEO_DECODER_SRC_PAD (self),
1643
1679
      (GstTaskFunction) gst_amc_video_dec_loop, decoder, NULL);
1644
1680
 
1645
 
  return TRUE;
 
1681
  return ret;
 
1682
 
 
1683
failed_configure:
 
1684
  GST_ERROR_OBJECT (self, "Failed to configure hardware codec");
 
1685
  gst_amc_format_free (format);
 
1686
  format = NULL;
 
1687
  return FALSE;
1646
1688
}
1647
1689
 
1648
1690
static gboolean