1 /**************************************************************************
3 * Copyright 2013 Advanced Micro Devices, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Christian König <christian.koenig@amd.com>
36 #include "pipe/p_video_codec.h"
38 #include "util/u_video.h"
39 #include "util/u_memory.h"
41 #include "vl/vl_video_buffer.h"
43 #include "../../winsys/radeon/drm/radeon_winsys.h"
44 #include "r600_pipe_common.h"
45 #include "radeon_video.h"
46 #include "radeon_vce.h"
48 #define CPB_SIZE (40 * 1024 * 1024)
51 * flush commands to the hardware
53 static void flush(struct rvce_encoder
*enc
)
55 enc
->ws
->cs_flush(enc
->cs
, RADEON_FLUSH_ASYNC
, 0);
59 static void dump_feedback(struct rvce_encoder
*enc
, struct rvid_buffer
*fb
)
61 uint32_t *ptr
= enc
->ws
->buffer_map(fb
->cs_handle
, enc
->cs
, PIPE_TRANSFER_READ_WRITE
);
63 fprintf(stderr
, "\n");
64 fprintf(stderr
, "encStatus:\t\t\t%08x\n", ptr
[i
++]);
65 fprintf(stderr
, "encHasBitstream:\t\t%08x\n", ptr
[i
++]);
66 fprintf(stderr
, "encHasAudioBitstream:\t\t%08x\n", ptr
[i
++]);
67 fprintf(stderr
, "encBitstreamOffset:\t\t%08x\n", ptr
[i
++]);
68 fprintf(stderr
, "encBitstreamSize:\t\t%08x\n", ptr
[i
++]);
69 fprintf(stderr
, "encAudioBitstreamOffset:\t%08x\n", ptr
[i
++]);
70 fprintf(stderr
, "encAudioBitstreamSize:\t\t%08x\n", ptr
[i
++]);
71 fprintf(stderr
, "encExtrabytes:\t\t\t%08x\n", ptr
[i
++]);
72 fprintf(stderr
, "encAudioExtrabytes:\t\t%08x\n", ptr
[i
++]);
73 fprintf(stderr
, "videoTimeStamp:\t\t\t%08x\n", ptr
[i
++]);
74 fprintf(stderr
, "audioTimeStamp:\t\t\t%08x\n", ptr
[i
++]);
75 fprintf(stderr
, "videoOutputType:\t\t%08x\n", ptr
[i
++]);
76 fprintf(stderr
, "attributeFlags:\t\t\t%08x\n", ptr
[i
++]);
77 fprintf(stderr
, "seiPrivatePackageOffset:\t%08x\n", ptr
[i
++]);
78 fprintf(stderr
, "seiPrivatePackageSize:\t\t%08x\n", ptr
[i
++]);
79 fprintf(stderr
, "\n");
80 enc
->ws
->buffer_unmap(fb
->cs_handle
);
85 * destroy this video encoder
87 static void rvce_destroy(struct pipe_video_codec
*encoder
)
89 struct rvce_encoder
*enc
= (struct rvce_encoder
*)encoder
;
90 if (enc
->stream_handle
) {
91 struct rvid_buffer fb
;
92 rvid_create_buffer(enc
->ws
, &fb
, 512, RADEON_DOMAIN_GTT
);
98 rvid_destroy_buffer(&fb
);
100 rvid_destroy_buffer(&enc
->cpb
);
101 enc
->ws
->cs_destroy(enc
->cs
);
105 static void rvce_begin_frame(struct pipe_video_codec
*encoder
,
106 struct pipe_video_buffer
*source
,
107 struct pipe_picture_desc
*picture
)
109 struct rvce_encoder
*enc
= (struct rvce_encoder
*)encoder
;
110 struct vl_video_buffer
*vid_buf
= (struct vl_video_buffer
*)source
;
111 struct pipe_h264_enc_picture_desc
*pic
= (struct pipe_h264_enc_picture_desc
*)picture
;
113 bool need_rate_control
=
114 enc
->pic
.rate_ctrl
.rate_ctrl_method
!= pic
->rate_ctrl
.rate_ctrl_method
||
115 enc
->pic
.quant_i_frames
!= pic
->quant_i_frames
||
116 enc
->pic
.quant_p_frames
!= pic
->quant_p_frames
||
117 enc
->pic
.quant_b_frames
!= pic
->quant_b_frames
;
121 enc
->get_buffer(vid_buf
->resources
[0], &enc
->handle
, &enc
->luma
);
122 enc
->get_buffer(vid_buf
->resources
[1], NULL
, &enc
->chroma
);
124 if (!enc
->stream_handle
) {
125 struct rvid_buffer fb
;
126 enc
->stream_handle
= rvid_alloc_stream_handle();
127 rvid_create_buffer(enc
->ws
, &fb
, 512, RADEON_DOMAIN_GTT
);
131 enc
->rate_control(enc
);
132 need_rate_control
= false;
133 enc
->config_extension(enc
);
134 enc
->motion_estimation(enc
);
136 enc
->pic_control(enc
);
139 //dump_feedback(enc, &fb);
140 rvid_destroy_buffer(&fb
);
145 if (need_rate_control
)
146 enc
->rate_control(enc
);
149 static void rvce_encode_bitstream(struct pipe_video_codec
*encoder
,
150 struct pipe_video_buffer
*source
,
151 struct pipe_resource
*destination
,
154 struct rvce_encoder
*enc
= (struct rvce_encoder
*)encoder
;
155 enc
->get_buffer(destination
, &enc
->bs_handle
, NULL
);
156 enc
->bs_size
= destination
->width0
;
158 *fb
= enc
->fb
= CALLOC_STRUCT(rvid_buffer
);
159 if (!rvid_create_buffer(enc
->ws
, enc
->fb
, 512, RADEON_DOMAIN_GTT
)) {
160 RVID_ERR("Can't create feedback buffer.\n");
167 static void rvce_end_frame(struct pipe_video_codec
*encoder
,
168 struct pipe_video_buffer
*source
,
169 struct pipe_picture_desc
*picture
)
171 struct rvce_encoder
*enc
= (struct rvce_encoder
*)encoder
;
175 static void rvce_get_feedback(struct pipe_video_codec
*encoder
,
176 void *feedback
, unsigned *size
)
178 struct rvce_encoder
*enc
= (struct rvce_encoder
*)encoder
;
179 struct rvid_buffer
*fb
= feedback
;
182 uint32_t *ptr
= enc
->ws
->buffer_map(fb
->cs_handle
, enc
->cs
, PIPE_TRANSFER_READ_WRITE
);
185 *size
= ptr
[4] - ptr
[9];
190 enc
->ws
->buffer_unmap(fb
->cs_handle
);
192 //dump_feedback(enc, fb);
193 rvid_destroy_buffer(fb
);
198 * flush any outstanding command buffers to the hardware
200 static void rvce_flush(struct pipe_video_codec
*encoder
)
204 static void rvce_cs_flush(void *ctx
, unsigned flags
)
209 struct pipe_video_codec
*rvce_create_encoder(struct pipe_context
*context
,
210 const struct pipe_video_codec
*templ
,
211 struct radeon_winsys
* ws
,
212 rvce_get_buffer get_buffer
)
214 struct r600_common_screen
*rscreen
= (struct r600_common_screen
*)context
->screen
;
215 struct rvce_encoder
*enc
;
217 if (!rscreen
->info
.vce_fw_version
) {
218 RVID_ERR("Kernel doesn't supports VCE!\n");
221 } else if (!rvce_is_fw_version_supported(rscreen
)) {
222 RVID_ERR("Unsupported VCE fw version loaded!\n");
226 enc
= CALLOC_STRUCT(rvce_encoder
);
231 enc
->base
.context
= context
;
233 enc
->base
.destroy
= rvce_destroy
;
234 enc
->base
.begin_frame
= rvce_begin_frame
;
235 enc
->base
.encode_bitstream
= rvce_encode_bitstream
;
236 enc
->base
.end_frame
= rvce_end_frame
;
237 enc
->base
.flush
= rvce_flush
;
238 enc
->base
.get_feedback
= rvce_get_feedback
;
239 enc
->get_buffer
= get_buffer
;
242 enc
->cs
= ws
->cs_create(ws
, RING_VCE
, NULL
);
244 RVID_ERR("Can't get command submission context.\n");
248 enc
->ws
->cs_set_flush_callback(enc
->cs
, rvce_cs_flush
, enc
);
250 if (!rvid_create_buffer(enc
->ws
, &enc
->cpb
, CPB_SIZE
, RADEON_DOMAIN_VRAM
)) {
251 RVID_ERR("Can't create CPB buffer.\n");
255 radeon_vce_40_2_2_init(enc
);
261 enc
->ws
->cs_destroy(enc
->cs
);
263 rvid_destroy_buffer(&enc
->cpb
);
270 * check if kernel has the right fw version loaded
272 bool rvce_is_fw_version_supported(struct r600_common_screen
*rscreen
)
274 return rscreen
->info
.vce_fw_version
== ((40 << 24) | (2 << 16) | (2 << 8));