1 #include <VLIB/video_controller.h>
2 #include <VLIB/video_packetizer.h>
3 #include <VLIB/Platform/video_utils.h>
5 #include <VP_Os/vp_os_malloc.h>
6 #include <VP_Os/vp_os_assert.h>
8 #include "p264_codec.h"
9 #include "p264_layers.h"
11 #include "p264_common.h"
13 #include <VP_Os/vp_os_print.h>
15 #define min(a,b) ((a)<(b)?(a):(b))
16 #define max(a,b) ((a)>(b)?(a):(b))
18 // macro helper to read an intra 4x4 mode using prediction
19 #define READ_INTRA_CODE(pred,dest_intra) \
21 video_read_data (stream,&code,1); \
29 video_read_data (stream,&code,3); \
33 dest_intra = code+1; \
36 // make a intra 4x4 prediction based on the upper and left 4x4 block intra mode (see p264 standard)
37 intra_4x4_mode_t make_boundary_pred(intra_4x4_mode_t* left_intra_4x4, uint32_t left_index, intra_4x4_mode_t * up_intra_4x4, uint32_t up_index,bool_t boundary_block)
39 intra_4x4_mode_t pred;
40 intra_4x4_mode_t left_mode,up_mode;
41 if (boundary_block == TRUE)
45 if (left_intra_4x4 == NULL)
46 left_mode = DC_4x4_MODE;
48 left_mode = left_intra_4x4[left_index];
50 if (up_intra_4x4 == NULL)
51 up_mode = DC_4x4_MODE;
53 up_mode = up_intra_4x4[up_index];
55 pred = min(left_mode,up_mode);
61 // write 16 intra_4x4 mode. Data should contains prediction on intra_4x4 (see p264 standard)
62 // example : data = [ pred (1bits) | code (3bits) ]
63 // if pred == 0 the prediction made over up and left block is correct. Thus no intra code has to bee transmitted
64 // if pred != 1, the prediction is wrong. The intra 4x4 mode should be transmitted using only 3 bits (see p264 standard)
65 void p264_write_intra_4x4 (video_stream_t* const stream, intra_4x4_mode_t* data)
70 if (((*data)&0x08) == 0)
72 // the prediction is good, signal it
73 video_write_data (stream,0,1);
77 // the prediction is false, transmit the intra 4x4 mode
78 video_write_data (stream,*data,4);
84 // TODO: this function should be moved to a dedicated file
85 void p264_read_mv(video_stream_t* const stream, video_gob_t* gobs, uint32_t i_blockline, uint32_t i_mb, uint32_t num_mb_per_line)
87 // this function reads a 16x16 mvp from a stream and reconstructs the correct mv
88 // it is assumed only 16x16 partition are used
91 // E is the current mb
93 // case 1 : A is unavailable, use {0,0} as its mv (A becomes available)
94 // case 2 : only A is available, use its mv as the prediction
95 // case 3 : C is unavailable, use C=D instead (C becomes available)
96 // case 4 : A,B,C are available
97 // for case 1,3,4 the prediction is the median(A,B,C)
99 // therefore the MB types over a P-frame are
102 // |1&2| 2 | ... | 2 | 2 |
104 // | 1 | 4 | ... | 4 | 3 |
110 int32_t pred_x,pred_y;
111 int32_t ax,ay,bx,by,cx,cy;
113 if (i_blockline == 0 && i_mb == 0)
115 // first MB (case 1&2)
119 else if (i_blockline == 0)
121 // first MB line (case 2)
122 pred_x = gobs[i_blockline].macroblocks[i_mb-1].inter_MV[0].x;
123 pred_y = gobs[i_blockline].macroblocks[i_mb-1].inter_MV[0].y;
127 // first MB column (case 1)
130 bx = gobs[i_blockline-1].macroblocks[i_mb].inter_MV[0].x;
131 by = gobs[i_blockline-1].macroblocks[i_mb].inter_MV[0].y;
132 cx = gobs[i_blockline-1].macroblocks[i_mb+1].inter_MV[0].x;
133 cy = gobs[i_blockline-1].macroblocks[i_mb+1].inter_MV[0].y;
134 pred_x = ax + bx + cx - min(ax,min(bx,cx)) - max(ax,max(bx,cx));
135 pred_y = ay + by + cy - min(ay,min(by,cy)) - max(ay,max(by,cy));
137 else if (i_mb == (num_mb_per_line-1))
139 // last column (case 3)
140 ax = gobs[i_blockline].macroblocks[i_mb-1].inter_MV[0].x;
141 ay = gobs[i_blockline].macroblocks[i_mb-1].inter_MV[0].y;
142 bx = gobs[i_blockline-1].macroblocks[i_mb].inter_MV[0].x;
143 by = gobs[i_blockline-1].macroblocks[i_mb].inter_MV[0].y;
144 cx = gobs[i_blockline-1].macroblocks[i_mb-1].inter_MV[0].x; // in fact D
145 cy = gobs[i_blockline-1].macroblocks[i_mb-1].inter_MV[0].y; // in fact D
146 pred_x = ax + bx + cx - min(ax,min(bx,cx)) - max(ax,max(bx,cx));
147 pred_y = ay + by + cy - min(ay,min(by,cy)) - max(ay,max(by,cy));
151 // others MB (case 4)
152 ax = gobs[i_blockline].macroblocks[i_mb-1].inter_MV[0].x;
153 ay = gobs[i_blockline].macroblocks[i_mb-1].inter_MV[0].y;
154 bx = gobs[i_blockline-1].macroblocks[i_mb].inter_MV[0].x;
155 by = gobs[i_blockline-1].macroblocks[i_mb].inter_MV[0].y;
156 cx = gobs[i_blockline-1].macroblocks[i_mb+1].inter_MV[0].x;
157 cy = gobs[i_blockline-1].macroblocks[i_mb+1].inter_MV[0].y;
158 pred_x = ax + bx + cx - min(ax,min(bx,cx)) - max(ax,max(bx,cx));
159 pred_y = ay + by + cy - min(ay,min(by,cy)) - max(ay,max(by,cy));
162 // read mv, add prediction and save
164 p264_decode_int(stream, &s_code);
165 gobs[i_blockline].macroblocks[i_mb].inter_MV[0].x = s_code+pred_x;
167 p264_decode_int(stream, &s_code);
168 gobs[i_blockline].macroblocks[i_mb].inter_MV[0].y = s_code+pred_y;
171 // TODO: this function should be moved to a dedicated file
172 // read 16 intra_4x4 mode transmitted with intra prediction (see p264 standard)
173 void p264_read_intra_4x4 (video_stream_t* const stream, video_gob_t* gobs, uint32_t i_blockline, uint32_t i_mb)
175 intra_4x4_mode_t* current_intra_4x4;
176 intra_4x4_mode_t* up_intra_4x4=NULL;
177 intra_4x4_mode_t* left_intra_4x4=NULL;
178 bool_t left_boundary_block = FALSE;
179 bool_t up_boundary_block = FALSE;
180 video_macroblock_t * mb;
181 intra_4x4_mode_t pred = DC_4x4_MODE;
184 // retrieve current mb, up and left intra 4x4 prediction if available
185 current_intra_4x4 = gobs[i_blockline].macroblocks[i_mb].intra_4x4_mode;
188 mb = &gobs[i_blockline-1].macroblocks[i_mb];
189 up_intra_4x4 = mb->intra_4x4_mode;
190 // check whether it's an intra 4x4 mb or not
191 if (mb->intra_type != INTRA_4x4)
197 up_boundary_block = TRUE;
201 mb = &gobs[i_blockline].macroblocks[i_mb-1];
202 // check whether it's an intra 4x4 mb or not
203 left_intra_4x4 = mb->intra_4x4_mode;
204 if (mb->intra_type != INTRA_4x4)
206 left_intra_4x4 = NULL;
210 left_boundary_block = TRUE;
213 pred = make_boundary_pred(left_intra_4x4,5,up_intra_4x4,10,up_boundary_block|left_boundary_block);
214 READ_INTRA_CODE(pred,current_intra_4x4[0]);
216 pred = make_boundary_pred(current_intra_4x4,0,up_intra_4x4,11,up_boundary_block);
217 READ_INTRA_CODE(pred,current_intra_4x4[1]);
219 pred = make_boundary_pred(left_intra_4x4,7,current_intra_4x4,0,left_boundary_block);
220 READ_INTRA_CODE(pred,current_intra_4x4[2]);
222 pred = min(current_intra_4x4[1],current_intra_4x4[2]);
223 READ_INTRA_CODE(pred,current_intra_4x4[3]);
226 pred = make_boundary_pred(current_intra_4x4,1,up_intra_4x4,14,up_boundary_block);
227 READ_INTRA_CODE(pred,current_intra_4x4[4]);
229 pred = make_boundary_pred(current_intra_4x4,4,up_intra_4x4,15,up_boundary_block);
230 READ_INTRA_CODE(pred,current_intra_4x4[5]);
232 pred = min(current_intra_4x4[4],current_intra_4x4[3]);
233 READ_INTRA_CODE(pred,current_intra_4x4[6]);
235 pred = min(current_intra_4x4[5],current_intra_4x4[6]);
236 READ_INTRA_CODE(pred,current_intra_4x4[7]);
239 pred = make_boundary_pred(left_intra_4x4,13,current_intra_4x4,2,left_boundary_block);
240 READ_INTRA_CODE(pred,current_intra_4x4[8]);
242 pred = min(current_intra_4x4[8],current_intra_4x4[3]);
243 READ_INTRA_CODE(pred,current_intra_4x4[9]);
245 pred = make_boundary_pred(left_intra_4x4,15,current_intra_4x4,8,left_boundary_block);
246 READ_INTRA_CODE(pred,current_intra_4x4[10]);
248 pred = min(current_intra_4x4[9],current_intra_4x4[10]);
249 READ_INTRA_CODE(pred,current_intra_4x4[11]);
252 pred = min(current_intra_4x4[9],current_intra_4x4[6]);
253 READ_INTRA_CODE(pred,current_intra_4x4[12]);
255 pred = min(current_intra_4x4[12],current_intra_4x4[7]);
256 READ_INTRA_CODE(pred,current_intra_4x4[13]);
258 pred = min(current_intra_4x4[11],current_intra_4x4[12]);
259 READ_INTRA_CODE(pred,current_intra_4x4[14]);
261 pred = min(current_intra_4x4[13],current_intra_4x4[14]);
262 READ_INTRA_CODE(pred,current_intra_4x4[15]);
266 void p264_write_block( video_stream_t* const stream, int16_t* data, uint32_t length)
268 int32_t code, run, num_coeff;
270 // count number of DC coeff
272 int16_t * p_data = data;
282 video_write_data( stream, 1, 1 ); // signal that there's no coeff
286 video_write_data( stream, 0, 1 ); // signal that there are coeffs
289 while( num_coeff > 0 )
299 p264_encode( stream, code, run, num_coeff );
306 void p264_read_block( video_stream_t* const stream, int16_t* data)
308 int32_t index, run, last;//, nc;
311 code = run = last = 0;
312 video_read_data( stream, &code, 1 ); // signal that there's no DC coeff
319 code = run = last = 0;
320 p264_decode( stream, &run, &code, &last);
331 C_RESULT p264_write_mb_layer(video_controller_t* controller, video_stream_t* stream, video_macroblock_t* mb, int32_t num_macro_blocks )
338 while( num_macro_blocks > 0 )
340 //PRINT ("p264_write_mb_layer : stream size %d stream used %d\n",stream->size,stream->used);
342 if (controller->picture_type == VIDEO_PICTURE_INTER)
344 // write all partition
345 for (i=0;i<mb->nb_partition;i++)
347 video_write_data( stream,mb->inter_partition_mode[i],3);
350 // write all motion vector
351 for (i=0;i<mb->nb_partition;i++)
354 s_code = (int32_t)mb->inter_MV[i].x;
355 p264_encode_int(stream, s_code);
356 s_code = (int32_t)mb->inter_MV[i].y;
357 p264_encode_int(stream, s_code);
360 // write residual data as an intra4x4
361 // write all 4x4 block luma AC coeff
363 data = ((MB_p264_t*)mb->data)->inter.AC_Y;
366 p264_write_block( stream, data, 16);
370 // write 4 DC U coeff
371 p264_write_block(stream,((MB_p264_t*)mb->data)->inter.DC_U,4);
375 data = &((MB_p264_t*)mb->data)->inter.AC_U[1];
378 p264_write_block( stream, data, 15);
382 // write 4 DC V coeff
383 p264_write_block(stream,((MB_p264_t*)mb->data)->inter.DC_V,4);
387 data = &((MB_p264_t*)mb->data)->inter.AC_V[1];
390 p264_write_block( stream, data, 15);
396 // write MB intra type (16x16 or 4x4)
397 video_write_data( stream, mb->intra_type, 1 );
398 // write intra chroma type
399 video_write_data (stream, mb->intra_chroma_8x8_mode,2);
400 if (mb->intra_type == INTRA_4x4)
402 // write all luma 4x4 prediction modes
403 p264_write_intra_4x4(stream,mb->intra_4x4_mode);
405 // write all 4x4 block luma AC coeff
407 data = ((MB_p264_t*)mb->data)->intra_4x4.AC_Y;
410 p264_write_block( stream, data, 16);
414 // write 4 DC U coeff
415 p264_write_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_U,4);
419 data = &((MB_p264_t*)mb->data)->intra_4x4.AC_U[1];
422 p264_write_block( stream, data, 15);
426 // write 4 DC V coeff
427 p264_write_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_V,4);
431 data = &((MB_p264_t*)mb->data)->intra_4x4.AC_V[1];
434 p264_write_block( stream, data, 15);
440 // write luma 16x16 prediction mode
441 video_write_data(stream, mb->intra_luma_16x16_mode,2);
444 p264_write_block( stream, ((MB_p264_t*)mb->data)->intra_16x16.DC_Y, 16);
446 // write 16 luma AC coeff block
448 data = &((MB_p264_t*)mb->data)->intra_16x16.AC_Y[1];
451 p264_write_block( stream, data, 15);
455 // write 4 DC U coeff
456 p264_write_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_U,4);
460 data = &((MB_p264_t*)mb->data)->intra_16x16.AC_U[1];
463 p264_write_block( stream, data, 15);
467 // write 4 DC V coeff
468 p264_write_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_V,4);
472 data = &((MB_p264_t*)mb->data)->intra_16x16.AC_V[1];
475 p264_write_block( stream, data, 15);
487 C_RESULT p264_read_mb_layer(video_controller_t* controller, video_stream_t* stream, video_gob_t* gobs, uint32_t i_blockline, uint32_t i_mb)
493 video_macroblock_t* mb;
494 mb = &gobs[i_blockline].macroblocks[i_mb];
496 vp_os_memset( mb->data, 0, sizeof(MB_p264_t));
498 if (controller->picture_type == VIDEO_PICTURE_INTER)
500 // for now p264 supports only one partition per macroblock
501 mb->nb_partition = 1;
502 // read all partition
503 for (i=0;i<mb->nb_partition;i++)
506 video_read_data( stream,&code,3);
507 mb->inter_partition_mode[i] = code;
510 // read all motion vector
511 p264_read_mv(stream, gobs, i_blockline, i_mb,controller->mb_blockline);
513 // read residual data as an intra 4x4
514 // read 16 4x4 block luma AC coeff
516 data = ((MB_p264_t*)mb->data)->inter.AC_Y;
519 p264_read_block( stream, data);
524 p264_read_block(stream,((MB_p264_t*)mb->data)->inter.DC_U);
528 data = &((MB_p264_t*)mb->data)->inter.AC_U[1];
531 p264_read_block( stream, data);
536 p264_read_block(stream,((MB_p264_t*)mb->data)->inter.DC_V);
540 data = &((MB_p264_t*)mb->data)->inter.AC_V[1];
543 p264_read_block( stream, data);
549 // read MB intra type
551 video_read_data(stream, &code, 1);
552 mb->intra_type = (intra_type_t)code;
554 // read intra chroma type
556 video_read_data(stream, &code, 2);
557 mb->intra_chroma_8x8_mode = (intra_8x8_chroma_mode_t) code;
559 if (mb->intra_type == INTRA_4x4)
561 // read all 4x4 modes
562 p264_read_intra_4x4(stream, gobs, i_blockline, i_mb);
564 // read 16 4x4 block luma AC coeff
566 data = ((MB_p264_t*)mb->data)->intra_4x4.AC_Y;
569 p264_read_block( stream, data);
574 p264_read_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_U);
578 data = &((MB_p264_t*)mb->data)->intra_4x4.AC_U[1];
581 p264_read_block( stream, data);
586 p264_read_block(stream,((MB_p264_t*)mb->data)->intra_4x4.DC_V);
590 data = &((MB_p264_t*)mb->data)->intra_4x4.AC_V[1];
593 p264_read_block( stream, data);
599 // write luma 16x16 prediction mode
601 video_read_data(stream, &code ,2);
602 mb->intra_luma_16x16_mode = code;
605 p264_read_block( stream, ((MB_p264_t*)mb->data)->intra_16x16.DC_Y);
607 // write 256 luma AC coeff
608 // Normally only 15 AC coeff per block 4x4 has to be sent
610 data = &((MB_p264_t*)mb->data)->intra_16x16.AC_Y[1];
613 p264_read_block( stream, data);
618 p264_read_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_U);
622 data = &((MB_p264_t*)mb->data)->intra_16x16.AC_U[1];
625 p264_read_block( stream, data);
630 p264_read_block(stream,((MB_p264_t*)mb->data)->intra_16x16.DC_V);
634 data = &((MB_p264_t*)mb->data)->intra_16x16.AC_V[1];
637 p264_read_block( stream, data);