837
835
"buffer_info->size: %d, gst_buffer_get_size (outbuf): %d",
838
836
buffer_info->size, gst_buffer_get_size (outbuf));
838
if (gst_buffer_n_memory (outbuf) >= 1 &&
839
(mem = gst_buffer_peek_memory (outbuf, 0))
840
&& gst_is_mir_image_memory (mem)) {
842
GST_DEBUG_OBJECT (self, "It is Mir image memory");
843
do_hardware_rendering = gst_mir_do_hardware_render (mem);
846
GST_DEBUG_OBJECT (self, "hardware_rendering: %d", do_hardware_rendering);
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");
845
if (gst_buffer_n_memory (outbuf) >= 1 &&
846
(mem = gst_buffer_peek_memory (outbuf, 0))
847
&& gst_is_mir_image_memory (mem)) {
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) {
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)) {
854
GST_DEBUG_OBJECT (self, "Doing fast software rendering");
856
gst_buffer_map (outbuf, &minfo, GST_MAP_WRITE);
857
orc_memcpy (minfo.data, buf->data + buffer_info->offset,
859
gst_buffer_unmap (outbuf, &minfo);
860
} else if (!do_hardware_rendering
861
&& buffer_info->size == gst_buffer_get_size (outbuf)) {
863
GST_DEBUG_OBJECT (self, "Doing fast software rendering");
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);
865
/* Disabled for now since this plugin does not support non-hardware accelerated
866
* video rendering at the moment.
868
GST_DEBUG_OBJECT (self, "Doing slow software line-by-line copying");
870
/* Different video format, try to convert */
871
switch (self->color_format) {
872
case COLOR_FormatYUV420Planar:{
873
GstVideoFrame vframe;
876
gint stride, slice_height;
877
gint src_stride, dest_stride;
880
stride = self->stride;
882
GST_ERROR_OBJECT (self, "Stride not set");
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);
892
GST_ERROR_OBJECT (self, "Slice height not set");
897
gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
898
for (i = 0; i < 3; i++) {
901
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
903
src_stride = (stride + 1) / 2;
904
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
907
src = buf->data + buffer_info->offset;
910
src += self->crop_top * stride;
911
src += self->crop_left;
912
row_length = self->width;
914
/* skip the Y plane */
915
src += slice_height * stride;
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;
925
/* skip the U plane */
926
src += ((slice_height + 1) / 2) * ((stride + 1) / 2);
929
dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
930
height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
932
for (j = 0; j < height; j++) {
933
orc_memcpy (dest, src, row_length);
938
gst_video_frame_unmap (&vframe);
942
case COLOR_TI_FormatYUV420PackedSemiPlanar:
943
case COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced:{
946
gint src_stride, dest_stride;
948
GstVideoFrame vframe;
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");
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++) {
961
src_stride = self->stride;
962
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
964
src_stride = GST_ROUND_UP_2 (self->stride);
965
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
968
src = buf->data + buffer_info->offset;
970
row_length = self->width;
972
src += (self->slice_height - self->crop_top / 2) * self->stride;
973
row_length = GST_ROUND_UP_2 (self->width);
976
dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
977
height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
979
for (j = 0; j < height; j++) {
980
orc_memcpy (dest, src, row_length);
985
gst_video_frame_unmap (&vframe);
989
case COLOR_QCOM_FormatYUV420SemiPlanar:
990
case COLOR_FormatYUV420SemiPlanar:{
993
gint src_stride, dest_stride, fixed_stride;
995
GstVideoFrame vframe;
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");
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;
1010
fixed_stride = self->stride;
1013
gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
1015
for (i = 0; i < 2; i++) {
1016
src_stride = fixed_stride;
1017
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
1019
src = buf->data + buffer_info->offset;
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;
1031
dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
1032
height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
1034
for (j = 0; j < height; j++) {
1035
orc_memcpy (dest, src, row_length);
1037
dest += dest_stride;
1040
gst_video_frame_unmap (&vframe);
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;
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;
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);
1065
if ((luma_size % TILE_GROUP_SIZE) != 0)
1066
luma_size = (((luma_size - 1) / TILE_GROUP_SIZE) + 1) * TILE_GROUP_SIZE;
1068
for (y = 0; y < tile_h_luma; y++) {
1069
size_t row_width = width;
1072
for (x = 0; x < tile_w; x++) {
1073
size_t tile_width = row_width;
1074
size_t tile_height = height;
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;
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;
1085
src_chroma += TILE_SIZE / 2;
1087
/* account for right columns */
1088
if (tile_width > TILE_WIDTH)
1089
tile_width = TILE_WIDTH;
1091
/* account for bottom rows */
1092
if (tile_height > TILE_HEIGHT)
1093
tile_height = TILE_HEIGHT;
1095
/* dest luma memory index for this tile */
1096
luma_idx = y * TILE_HEIGHT * dest_luma_stride + x * TILE_WIDTH;
1098
/* dest chroma memory index for this tile */
1099
/* XXX: remove divisions */
1101
y * TILE_HEIGHT / 2 * dest_chroma_stride + x * TILE_WIDTH;
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;
1109
memcpy (dest_luma + luma_idx, src_luma, tile_width);
1110
src_luma += TILE_WIDTH;
1111
luma_idx += dest_luma_stride;
1113
memcpy (dest_chroma + chroma_idx, src_chroma, tile_width);
1114
src_chroma += TILE_WIDTH;
1115
chroma_idx += dest_chroma_stride;
1117
row_width -= TILE_WIDTH;
1119
height -= TILE_HEIGHT;
1121
gst_video_frame_unmap (&vframe);
1127
GST_ERROR_OBJECT (self, "Unsupported color format %d",
1128
self->color_format);
1133
/* Render and release the output buffer back to the decoder */
1134
err = media_codec_release_output_buffer (self->codec->codec_delegate, 0);
871
/* Disabled for now since this plugin does not support non-hardware accelerated
872
* video rendering at the moment.
874
GST_DEBUG_OBJECT (self,
875
"Doing slow software line-by-line copying with format conversion");
877
/* Different video format, try to convert */
878
switch (self->color_format) {
879
case COLOR_FormatYUV420Planar:{
880
GstVideoFrame vframe;
883
gint stride, slice_height;
884
gint src_stride, dest_stride;
887
stride = self->stride;
889
GST_ERROR_OBJECT (self, "Stride not set");
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);
899
GST_ERROR_OBJECT (self, "Slice height not set");
904
gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
905
for (i = 0; i < 3; i++) {
908
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
910
src_stride = (stride + 1) / 2;
911
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
914
src = buf->data + buffer_info->offset;
917
src += self->crop_top * stride;
918
src += self->crop_left;
919
row_length = self->width;
921
/* skip the Y plane */
922
src += slice_height * stride;
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;
932
/* skip the U plane */
933
src += ((slice_height + 1) / 2) * ((stride + 1) / 2);
936
dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
937
height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
939
for (j = 0; j < height; j++) {
940
orc_memcpy (dest, src, row_length);
945
gst_video_frame_unmap (&vframe);
949
case COLOR_TI_COLOR_FormatYUV420PackedSemiPlanar:
950
case COLOR_TI_FormatYUV420PackedSemiPlanar:
951
case COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced:{
954
gint src_stride, dest_stride;
956
GstVideoFrame vframe;
958
GST_DEBUG_OBJECT (self,
959
"COLOR_TI_COLOR_FormatYUV420PackedSemiPlanar conversion");
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");
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++) {
972
src_stride = self->stride;
973
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
975
src_stride = GST_ROUND_UP_2 (self->stride);
976
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
979
src = buf->data + buffer_info->offset;
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);
986
row_length = self->width;
988
src += (self->slice_height - self->crop_top / 2) * self->stride;
989
row_length = GST_ROUND_UP_2 (self->width);
992
dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
993
height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
995
for (j = 0; j < height; j++) {
997
GST_DEBUG_OBJECT (self,
998
"Copying data row (dest: %p, src: %p, row_length: %d", dest,
1001
orc_memcpy (dest, src, row_length);
1003
dest += dest_stride;
1005
GST_DEBUG_OBJECT (self,
1006
"Finished copying data row (src_stride: %d, dst_stride: %d",
1007
src_stride, dest_stride);
1011
gst_video_frame_unmap (&vframe);
1015
case COLOR_QCOM_FormatYUV420SemiPlanar:
1016
case COLOR_FormatYUV420SemiPlanar:{
1019
gint src_stride, dest_stride, fixed_stride;
1021
GstVideoFrame vframe;
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");
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;
1036
fixed_stride = self->stride;
1039
gst_video_frame_map (&vframe, info, outbuf, GST_MAP_WRITE);
1041
for (i = 0; i < 2; i++) {
1042
src_stride = fixed_stride;
1043
dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i);
1045
src = buf->data + buffer_info->offset;
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;
1057
dest = GST_VIDEO_FRAME_COMP_DATA (&vframe, i);
1058
height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i);
1060
for (j = 0; j < height; j++) {
1061
orc_memcpy (dest, src, row_length);
1063
dest += dest_stride;
1066
gst_video_frame_unmap (&vframe);
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;
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;
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);
1091
if ((luma_size % TILE_GROUP_SIZE) != 0)
1093
(((luma_size - 1) / TILE_GROUP_SIZE) + 1) * TILE_GROUP_SIZE;
1095
for (y = 0; y < tile_h_luma; y++) {
1096
size_t row_width = width;
1099
for (x = 0; x < tile_w; x++) {
1100
size_t tile_width = row_width;
1101
size_t tile_height = height;
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;
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;
1112
src_chroma += TILE_SIZE / 2;
1114
/* account for right columns */
1115
if (tile_width > TILE_WIDTH)
1116
tile_width = TILE_WIDTH;
1118
/* account for bottom rows */
1119
if (tile_height > TILE_HEIGHT)
1120
tile_height = TILE_HEIGHT;
1122
/* dest luma memory index for this tile */
1123
luma_idx = y * TILE_HEIGHT * dest_luma_stride + x * TILE_WIDTH;
1125
/* dest chroma memory index for this tile */
1126
/* XXX: remove divisions */
1128
y * TILE_HEIGHT / 2 * dest_chroma_stride + x * TILE_WIDTH;
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;
1136
memcpy (dest_luma + luma_idx, src_luma, tile_width);
1137
src_luma += TILE_WIDTH;
1138
luma_idx += dest_luma_stride;
1140
memcpy (dest_chroma + chroma_idx, src_chroma, tile_width);
1141
src_chroma += TILE_WIDTH;
1142
chroma_idx += dest_chroma_stride;
1144
row_width -= TILE_WIDTH;
1146
height -= TILE_HEIGHT;
1148
gst_video_frame_unmap (&vframe);
1154
GST_ERROR_OBJECT (self, "Unsupported color format %d",
1155
self->color_format);
1161
/* Just release the output buffer back to the decoder */
1163
media_codec_release_output_buffer (self->codec->codec_delegate, 0, FALSE);
1136
1165
GST_WARNING_OBJECT (self,
1137
1166
"Failed to release output buffer. Rendering will probably be affected (err: %d).",