3 #include "dma_malloc.h"
4 #include "video_config.h"
5 #include "video_p264_p6.h"
6 #include "video_utils_p6.h"
7 #include <VP_Os/vp_os_malloc.h>
8 #include "P6_h264_reg.h"
9 #include <VLIB/P264/p264_common.h>
10 #include <VLIB/P264/p264_zigzag.h>
12 #include <VP_Os/vp_os_print.h>
13 #include <sys/ioctl.h>
14 #include <sys/types.h>
17 #include <parrot/p264/p264_p6_ioctl.h>
20 #define CHECK_P264_IOCTL(a) if((a)<0) { PRINT("p264 ioctl failed (%s)\n",#a); return C_FAIL;}
21 //#define H264_P6_DEBUG
22 //#define H264_P6_PFRAME_DEBUG
24 // h264 picture parameters
25 static uint8_t* current_Y;
26 static uint8_t* current_Cb;
27 static uint8_t* current_Cr;
28 static uint32_t current_width;
29 static uint32_t current_height;
30 static bool_t I_encoding;
32 static uint8_t* h264_ref_frame; // frame decoded by encoder as a reference
33 static uint8_t* h264_deb_frame; // frame decoded by encoder as a reference
34 static p264_p6_raw_reg_results_t h264_raw_result[400]; // chroma_mode, intra_mode, MV, ...
36 static int h264_fd = -1;
38 C_RESULT video_p264_p6_init(void)
41 h264_fd = open("/dev/p264_p6", O_RDWR|O_NONBLOCK);
44 PRINT("p264 driver not found...\n");
48 // init local variable
49 // h264 picture parameters
55 h264_deb_frame = NULL;
56 h264_ref_frame = NULL;
61 #ifdef HAS_P264_FTRANSFORM
62 C_RESULT video_p264_prepare_slice ( video_controller_t* controller, const vp_api_picture_t* blockline)
64 // picture dimensions change ?
65 if (controller->width != current_width || controller->height != current_height)
67 // realloc a YUV 4:2:0 reference frame
68 h264_ref_frame = (uint8_t*)dma_realloc(h264_ref_frame,controller->width*controller->height*3/2);
69 h264_deb_frame = (uint8_t*)dma_realloc(h264_deb_frame,controller->width*controller->height*3/2);
70 current_width = controller->width;
71 current_height = controller->height;
73 if (current_width > CIF_WIDTH || current_height > CIF_HEIGHT)
74 PRINT("resolutions above CIF are not supported by P6 h264 ip\n");
75 // set search window size
76 // ... use default value
78 uint32_t value = P264_RES(current_width,current_height);
79 CHECK_P264_IOCTL(ioctl(h264_fd, P264_SET_DIM, &value))
82 PRINT ("H264 IP : new frame dimensions %dx%d\n",current_width,current_height);
86 // swap DEB and ref frames
88 p_tmp = h264_deb_frame;
89 h264_deb_frame = h264_ref_frame;
90 h264_ref_frame = p_tmp;
93 uint32_t value = (uint32_t)dma_virt2phy(h264_deb_frame);
94 CHECK_P264_IOCTL(ioctl(h264_fd, P264_SET_DEB_FRAME, &value))
96 dma_flush_inv( (uint32_t)h264_deb_frame, current_width*current_height*3/2);
98 // set reference frame
99 value = (uint32_t)dma_virt2phy(h264_ref_frame);
100 CHECK_P264_IOCTL(ioctl(h264_fd, P264_SET_REF_FRAME, &value))
101 dma_flush_inv( (uint32_t)h264_ref_frame, current_width*current_height*3/2);
103 CHECK_P264_IOCTL(ioctl(h264_fd, P264_SET_FRAME_TYPE, &(controller->picture_type)))
105 // devrait pouvoir sauter
106 if (controller->picture_type == VIDEO_PICTURE_INTRA)
111 // retrieve picture pointers
112 current_Y = blockline->y_buf;
113 current_Cb = blockline->cb_buf;
114 current_Cr = blockline->cr_buf;
116 p264_p6_input_buf_t input_buf;
117 input_buf.phys_Y = (uint32_t)dma_virt2phy(current_Y);
118 input_buf.phys_Cb = (uint32_t)dma_virt2phy(current_Cb);
119 input_buf.phys_Cr = (uint32_t)dma_virt2phy(current_Cr);
120 CHECK_P264_IOCTL(ioctl(h264_fd, P264_SET_INPUT_BUF, &input_buf))
123 dma_flush_inv( (uint32_t)current_Y, current_width*current_height);
124 dma_flush_inv( (uint32_t)current_Cb, (current_width*current_height>>2));
125 dma_flush_inv( (uint32_t)current_Cr, (current_width*current_height>>2));
128 dma_flush_inv( (uint32_t)controller->cache, (controller->width>>4) * (controller->height>>4) * sizeof(MB_p264_t));
133 static void intra_pred_4x4_p6_to_list (uint32_t intra_pred_4x4_0, uint32_t intra_pred_4x4_1, intra_4x4_mode_t* out)
138 *out++ = (intra_4x4_mode_t) (intra_pred_4x4_0 & 0x0F);
139 intra_pred_4x4_0 = intra_pred_4x4_0>>4;
143 *out++ = (intra_4x4_mode_t) (intra_pred_4x4_1 & 0x0F);
144 intra_pred_4x4_1 = intra_pred_4x4_1>>4;
148 void P6_get_MV (MV_XY_t *mv,uint32_t num_mv, uint32_t* raw_mv_tab)
150 uint32_t mv_2k_result;
151 mv_2k_result = raw_mv_tab[(num_mv&0x0E)>>1];
152 if ((num_mv&0x01) == 0)
154 mv->x = (mv_2k_result&0x000000FF)>>0;
156 mv->y = (mv_2k_result&0x0000FF00)>>8;
161 mv->x = (mv_2k_result&0x00FF0000)>>16;
163 mv->y = (mv_2k_result&0xFF000000)>>24;
169 // encode num_macro_blocks MB
170 C_RESULT video_p264_encode_MB(uint32_t num_macro_blocks, video_macroblock_t* macroblock ,int32_t qp)
172 if (num_macro_blocks > 0)
174 // launch (num_macro_block - num_pending) encoding
175 MB_p264_t* MB_P6 = (MB_p264_t*)macroblock->data;
178 CHECK_P264_IOCTL(ioctl(h264_fd, P264_SET_QP, &qp))
180 // set output data addr
181 p264_p6_output_buf_t output_buf;
182 output_buf.phys_output = (uint32_t)dma_virt2phy(MB_P6);
183 output_buf.reg_output = h264_raw_result;
184 CHECK_P264_IOCTL(ioctl(h264_fd, P264_SET_OUTPUT_BUF, &output_buf))
187 CHECK_P264_IOCTL(ioctl(h264_fd, P264_ENCODE_NEXT_MB, &num_macro_blocks))
195 // get encoded num_macro_blocks MB
196 int32_t video_p264_get_encoded_MB(uint32_t num_macro_blocks, video_macroblock_t* macroblock)
198 // retrieve and process available MBs
199 if (num_macro_blocks > 0)
201 // wait hardware completion
202 CHECK_P264_IOCTL(ioctl(h264_fd, P264_WAIT_ENCODE, &num_macro_blocks))
204 if (num_macro_blocks != 0)
206 // at this point num_macro_block h264_raw_result is filled with me_result and MV
208 for (i=0;i<num_macro_blocks;i++)
210 MB_p264_t* MB_P6 = (MB_p264_t*)(macroblock[i].data);
212 if (I_encoding == FALSE)
214 // save MB partition and MV
215 if (INTER_16_8_PARTITION(h264_raw_result[i].me_result) == 0)
218 // save partition mode
219 macroblock[i].inter_partition_mode[0] = INTER_PART_16x16;
220 // save corresponding MV
221 P6_get_MV(&(macroblock[i].inter_MV[0]),0,h264_raw_result[i].pred_result);
222 macroblock[i].nb_partition = 1;
224 else if (INTER_16_8_PARTITION(h264_raw_result[i].me_result) == 1)
227 // save partition mode
228 macroblock[i].inter_partition_mode[0] = INTER_PART_16x8;
229 macroblock[i].inter_partition_mode[1] = INTER_PART_16x8;
230 // save corresponding MV
231 P6_get_MV(¯oblock[i].inter_MV[0],0,h264_raw_result[i].pred_result);
232 P6_get_MV(¯oblock[i].inter_MV[1],8,h264_raw_result[i].pred_result);
233 macroblock[i].nb_partition = 2;
235 else if (INTER_16_8_PARTITION(h264_raw_result[i].me_result) == 2)
238 // save partition mode
239 macroblock[i].inter_partition_mode[0] = INTER_PART_8x16;
240 macroblock[i].inter_partition_mode[1] = INTER_PART_8x16;
241 // save corresponding MV
242 P6_get_MV(¯oblock[i].inter_MV[0],0,h264_raw_result[i].pred_result);
243 P6_get_MV(¯oblock[i].inter_MV[1],4,h264_raw_result[i].pred_result);
244 macroblock[i].nb_partition = 2;
246 // 8x8 8x4 4x8 4x4 cases missing
248 PRINT ("wrong partition (or not supported) result %d\n",INTER_16_8_PARTITION(h264_raw_result[i].me_result));
250 // patch DC chroma coeff
251 // P6 h264 IP performs a zigzag on DC coeff. It should not.
252 MB_P6->inter.DC_U[3] = MB_P6->inter.dummy_DC_U[0];
253 MB_P6->inter.DC_V[3] = MB_P6->inter.dummy_DC_V[0];
255 #ifdef H264_P6_PFRAME_DEBUG
257 for (i=0;i<prev_macroblock->nb_partition;i++)
259 PRINT ("partition[%d]=%d - MV (%d,%d)\n",i,macroblock[i].inter_partition_mode[i],macroblock[i].inter_MV[i].x,macroblock[i].inter_MV[i].y);
266 PRINT ("me result 0x%x\n",h264_raw_result[i].me_result);
267 PRINT ("--> Y intra mode %d\n",(h264_raw_result[i].me_result&0x1F));
268 PRINT ("--> Chroma intra mode %d\n",CHROMA_MODE(h264_raw_result[i].me_result));
271 if (IS_INTRA_4x4(h264_raw_result[i].me_result))
273 // patch DC chroma coeff
274 // P6 h264 IP performs a zigzag on DC coeff. It should not.
275 MB_P6->intra_4x4.DC_U[3] = MB_P6->intra_4x4.dummy_DC_U[0];
276 MB_P6->intra_4x4.DC_V[3] = MB_P6->intra_4x4.dummy_DC_V[0];
277 // set macroblock type
278 macroblock[i].intra_type = INTRA_4x4;
279 // save 4x4 intra luma result
280 intra_pred_4x4_p6_to_list (h264_raw_result[i].intra_pred_4x4_0, h264_raw_result[i].intra_pred_4x4_1, macroblock[i].intra_4x4_mode);
282 PRINT ("intra 4x4 pred result 0x%x\n",h264_raw_result[i].intra_pred_4x4_0);
283 PRINT ("intra 4x4 pred result 0x%x\n",h264_raw_result[i].intra_pred_4x4_1);
288 // patch DC chroma coeff
289 // P6 h264 IP performs a zigzag on DC coeff. It should not.
290 MB_P6->intra_16x16.DC_U[3] = MB_P6->intra_16x16.dummy_DC_U[0];
291 MB_P6->intra_16x16.DC_V[3] = MB_P6->intra_16x16.dummy_DC_V[0];
292 // set macroblock type
293 macroblock[i].intra_type = INTRA_16x16;
294 // save 16x16 luma result
295 macroblock[i].intra_luma_16x16_mode = INTRA_16x16_MODE(h264_raw_result[i].me_result);
297 printf("luma 16x16 pred %d\n",INTRA_16x16_MODE(h264_raw_result[i].me_result));
300 // zagzig DC luma (P6 bug fix)
301 int16_t tmp_zagzig[16];
302 zagzig_4x4 (MB_P6->intra_16x16.DC_Y, tmp_zagzig);
303 vp_os_memcpy(MB_P6->intra_16x16.DC_Y,tmp_zagzig,16*sizeof(int16_t));
307 macroblock[i].intra_chroma_8x8_mode = CHROMA_MODE(h264_raw_result[i].me_result);
312 return num_macro_blocks;
317 C_RESULT video_p264_p6_close(void)
319 if (h264_ref_frame != NULL)
320 dma_free (h264_ref_frame);
321 h264_ref_frame = NULL;
322 if (h264_deb_frame != NULL)
323 dma_free (h264_deb_frame);
328 h264_deb_frame = NULL;