1 #include <VLIB/Platform/video_utils.h>
2 #include <VLIB/Platform/video_config.h>
4 #include "video_p264.h"
5 #include <VLIB/video_packetizer.h>
6 #include "p264_codec.h"
7 #include <VLIB/video_quantizer.h>
9 #include <VP_Os/vp_os_malloc.h>
10 #include <VP_Os/vp_os_assert.h>
11 #include <VP_Os/vp_os_types.h>
12 #include <VP_Os/elinux/vp_os_ltt.h>
14 #include <VP_Os/vp_os_print.h>
17 #define P264_DEFAULT_QUANTIZATION 20
19 const p264_codec_t p264_codec = {
20 p264_encode_blockline,
21 p264_decode_blockline,
27 void p264_codec_alloc( video_controller_t* controller )
29 video_codec_t* video_codec;
31 video_codec = (video_codec_t*) vp_os_malloc( sizeof(p264_codec) );
33 vp_os_memcpy(video_codec, &p264_codec, sizeof(p264_codec));
35 controller->video_codec = video_codec;
39 void p264_realloc_ref (video_controller_t* controller)
41 // realloc internal p264 buffers and make last decoded picture as the reference
42 p264_codec_t* video_codec;
43 video_codec = (p264_codec_t*)controller->video_codec;
44 if (controller->width != video_codec->ref_picture.width && controller->height != video_codec->ref_picture.height)
46 // resolution has changed, realloc buffers
47 video_codec->ref_picture.width = controller->width;
48 video_codec->ref_picture.height = controller->height;
49 video_codec->decoded_picture.width = controller->width;
50 video_codec->decoded_picture.height = controller->height;
52 // allocate a YUV 4:2:0 ref frame
53 video_codec->ref_picture.y_buf = (uint8_t*)vp_os_realloc(video_codec->ref_picture.y_buf,controller->width*controller->height*3/2);
54 video_codec->decoded_picture.y_buf = (uint8_t*)vp_os_realloc(video_codec->decoded_picture.y_buf,controller->width*controller->height*3/2);
55 if (video_codec->ref_picture.y_buf == NULL || video_codec->decoded_picture.y_buf == NULL)
57 PRINT("p264 ref realloc failed\n");
61 video_codec->ref_picture.cb_buf = video_codec->ref_picture.y_buf + video_codec->ref_picture.width*video_codec->ref_picture.height;
62 video_codec->ref_picture.cr_buf = video_codec->ref_picture.cb_buf + (video_codec->ref_picture.width*video_codec->ref_picture.height)/4;
63 video_codec->ref_picture.y_line_size = video_codec->ref_picture.width;
64 video_codec->ref_picture.cb_line_size = video_codec->ref_picture.width>>1;
65 video_codec->ref_picture.cr_line_size = video_codec->ref_picture.width>>1;
67 video_codec->decoded_picture.cb_buf = video_codec->decoded_picture.y_buf + video_codec->decoded_picture.width*video_codec->decoded_picture.height;
68 video_codec->decoded_picture.cr_buf = video_codec->decoded_picture.cb_buf + (video_codec->decoded_picture.width*video_codec->decoded_picture.height)/4;
69 video_codec->decoded_picture.y_line_size = video_codec->decoded_picture.width;
70 video_codec->decoded_picture.cb_line_size = video_codec->decoded_picture.width>>1;
71 video_codec->decoded_picture.cr_line_size = video_codec->decoded_picture.width>>1;
74 // swap decoded_picture and ref picture
77 p_swap = video_codec->ref_picture.y_buf;
78 video_codec->ref_picture.y_buf = video_codec->decoded_picture.y_buf;
79 video_codec->decoded_picture.y_buf = p_swap;
81 p_swap = video_codec->ref_picture.cb_buf;
82 video_codec->ref_picture.cb_buf = video_codec->decoded_picture.cb_buf;
83 video_codec->decoded_picture.cb_buf = p_swap;
85 p_swap = video_codec->ref_picture.cr_buf;
86 video_codec->ref_picture.cr_buf = video_codec->decoded_picture.cr_buf;
87 video_codec->decoded_picture.cr_buf = p_swap;
90 void p264_codec_free( video_controller_t* controller )
92 p264_codec_t* p264_codec = (p264_codec_t*) controller->video_codec;
94 if( p264_codec != NULL )
96 if (p264_codec->ref_picture.y_buf != NULL)
97 vp_os_free(p264_codec->ref_picture.y_buf);
98 if (p264_codec->decoded_picture.y_buf != NULL)
99 vp_os_free(p264_codec->decoded_picture.y_buf);
100 vp_os_free( p264_codec );
101 controller->video_codec = NULL;
106 static C_RESULT p264_flush_stream( video_stream_t* out, video_stream_t* in )
108 // They are still data in cache
109 // Always copy a number of bytes that is a times of 4.
110 // Only for the last copy, we can have exactly the number of bytes left
111 int32_t offset, size;
112 uint32_t out_stream_size;
114 if( in->length != 32 )
116 // flush & reset internal stream
117 video_write_data( in, 0, in->length+1 );
121 out_stream_size = out->size & ~3; // Round to the highest times of 4 available
123 offset = in->index - (in->used >> 2);
124 size = ( in->used < out_stream_size ) ? in->used : out_stream_size;
126 vp_os_memcpy(out->bytes, in->bytes + offset, size);
128 out->index = size >> 2;
136 static C_RESULT p264_load_stream( video_stream_t* out, video_stream_t* in )
138 // We cache as many blockline as possible
140 bool_t found, last_zero, last_zero_temp;
143 int32_t value, nb_bytes;
144 uint32_t in_index = (in->used >> 2) - 1;
146 // -> start looking for last blockline's end
149 if( in->index == 0 ) // First call, we look for full blocklines
153 while( (in_index > in->index) && !found )
155 value = in->bytes[in_index];
157 last_zero_temp = (value & 0xFF) == 0; // 0x??????00
158 found = last_zero_temp & last_zero;
162 last_zero = last_zero_temp;
165 last_zero_temp = (value & 0xFF) == 0; // 0x????00??
166 found = last_zero_temp & last_zero;
170 last_zero = last_zero_temp;
173 last_zero_temp = (value & 0xFF) == 0; // 0x??00????
174 found = last_zero_temp & last_zero;
178 in_index--; // Handle both the special case where blockline is dword aligned &
179 // blockline start is still not found
181 last_zero = last_zero_temp;
184 last_zero_temp = (value & 0xFF) == 0; // 0x00??????
185 found = last_zero_temp & last_zero;
189 last_zero = last_zero_temp;
199 // configure parameters for memcpy
203 nb_bytes = in->used - in->index * 4;
209 // cache only data containing full blocklines
210 nb_bytes = (in_index - in->index) * 4;
215 // Realloc internal stream to have enough space to hold all required data
216 while( out->used + nb_bytes >= out->size )
218 out->bytes = vp_os_realloc( out->bytes, out->size + 2048 ); // Add 2KB to internal stream
222 dst = (uint8_t*)&out->bytes[0];
225 src = (uint8_t*)&in->bytes[0];
228 vp_os_memcpy( dst, src, nb_bytes );
230 out->used += nb_bytes;
231 in->index = in_index;
233 VP_OS_ASSERT( out->used <= out->size );
238 C_RESULT p264_pack_controller( video_controller_t* controller )
240 video_stream_t* stream = &controller->in_stream;
241 p264_codec_t* p264_codec = (p264_codec_t*) controller->video_codec;
242 p264_picture_layer_t* picture_layer;
243 p264_gob_layer_t* gob;
246 picture_layer = &p264_codec->picture_layer;
248 video_stuff8( stream );
250 picture_layer->gobs = (p264_gob_layer_t*) controller->gobs;
251 gob = &picture_layer->gobs[controller->blockline];
253 video_write_data( stream, MAKE_START_CODE(controller->blockline), 22 );
255 if( controller->blockline == 0 )
257 picture_layer->quant = gob->quant;
258 p264_write_picture_layer( controller, stream );
262 p264_write_gob_layer( stream, gob );
268 C_RESULT p264_unpack_controller( video_controller_t* controller )
270 uint32_t start_code = 0;
271 video_stream_t* stream = &controller->in_stream;
272 p264_codec_t* p264_codec = (p264_codec_t*) controller->video_codec;
273 p264_picture_layer_t* picture_layer;
274 p264_gob_layer_t* gob;
277 picture_layer = &p264_codec->picture_layer;
279 video_align8( stream );
280 video_read_data( stream, &start_code, 22 );
282 controller->blockline = start_code & 0x1F;
283 start_code &= ~0x1F; // TODO Check if compiler use arm instruction bic
285 VP_OS_ASSERT( controller->blockline == 0x1F ||
286 controller->num_blockline == 0 || // Check if cache is allocated for current picture
287 (controller->num_blockline > 0 && controller->blockline < controller->num_blockline) );
289 if( start_code == PICTURE_START_CODE )
291 if( controller->blockline == 0x1F )
293 controller->picture_complete = TRUE;
297 if( controller->blockline == 0 )
300 p264_read_picture_layer( controller, stream );
301 p264_realloc_ref(controller);
302 picture_layer->gobs = (p264_gob_layer_t*) controller->gobs;
303 gob = &picture_layer->gobs[controller->blockline];
305 gob->quant = picture_layer->quant;
309 picture_layer->gobs = (p264_gob_layer_t*) controller->gobs;
310 gob = &picture_layer->gobs[controller->blockline];
312 p264_read_gob_layer( stream, gob );
320 C_RESULT p264_encode_blockline( video_controller_t* controller, const vp_api_picture_t* blockline, bool_t picture_complete )
322 video_codec_t* video_codec;
323 //int16_t *in = NULL;//, *out = NULL;
324 int32_t num_macro_blocks = 0;
325 video_macroblock_t* macroblock = NULL;
326 video_picture_context_t blockline_ctx;
329 video_stream_t* stream = &controller->in_stream;
331 if( stream->used*2 >= stream->size )
333 uint32_t add = 32 - clz(stream->used/controller->blockline); // estimate the log2 size of a blockline in the stream
334 add = 1<<(add+1); // major and compute addition buffer size
335 stream->bytes = vp_os_realloc( stream->bytes, stream->size + add ); // Add some byte to internal stream
339 video_codec = controller->video_codec;
340 controller->picture_complete = picture_complete;
341 controller->blockline = blockline->blockline;
343 blockline_ctx.y_src = blockline->y_buf;
344 blockline_ctx.cb_src = blockline->cb_buf;
345 blockline_ctx.cr_src = blockline->cr_buf;
346 blockline_ctx.y_woffset = blockline->y_line_size;
347 blockline_ctx.c_woffset = blockline->cb_line_size;
348 blockline_ctx.y_hoffset = blockline->y_line_size * MCU_HEIGHT;
350 gobs = &controller->gobs[controller->blockline];
351 gobs->quant = controller->quant;
352 macroblock = &gobs->macroblocks[0];
354 if (blockline->blockline == 0)
356 if (controller->resolution_changed == TRUE)
358 // resolution changed, reset ip_counter to force I frame encoding
359 ((p264_codec_t*)video_codec)->ip_counter = 0;
361 if ((((p264_codec_t*)video_codec)->ip_counter%(NB_P_FRAMES+1))==0)
363 video_controller_set_picture_type( controller, VIDEO_PICTURE_INTRA );
364 ((p264_codec_t*)(controller->video_codec))->picture_layer.picture_type = VIDEO_PICTURE_INTRA;
368 video_controller_set_picture_type( controller, VIDEO_PICTURE_INTER );
369 ((p264_codec_t*)(controller->video_codec))->picture_layer.picture_type = VIDEO_PICTURE_INTER;
371 ((p264_codec_t*)video_codec)->ip_counter++;
373 // it's a new picture, prepare slice
374 video_p264_prepare_slice (controller,blockline);
377 p264_pack_controller( controller );
379 num_macro_blocks = controller->mb_blockline;
382 if (blockline->blockline == 0)
383 // TODO: next line is possible only when full frame is available (i.e. blokline mode not enabled). should not assume that.
384 video_p264_encode_MB(controller->mb_blockline*controller->num_blockline,macroblock, gobs->quant);
386 while (num_macro_blocks)
388 int32_t num_mb_ready = video_p264_get_encoded_MB(num_macro_blocks,macroblock);
391 num_macro_blocks -= num_mb_ready;
392 p264_write_mb_layer(controller, stream, macroblock, num_mb_ready );
393 macroblock += num_mb_ready;
398 ///> Packetize Data to output buffer
399 RTMON_USTART(VIDEO_VLIB_PACKET);
400 macroblock = &gobs->macroblocks[0];
402 ///> Control Stream size
404 if (controller->target_size > 0)
406 // compute i_p_ratio && target_size
407 uint32_t target_size;
409 if (((p264_codec_t*)video_codec)->last_I_size !=0 && ((p264_codec_t*)video_codec)->last_P_size !=0)
410 i_p_ratio = (float32_t)((p264_codec_t*)video_codec)->last_P_size/(float32_t)((p264_codec_t*)video_codec)->last_I_size;
414 if (controller->picture_type == VIDEO_PICTURE_INTRA)
415 target_size = (NB_P_FRAMES + 1)*controller->target_size/(1+NB_P_FRAMES*i_p_ratio);
417 target_size = (NB_P_FRAMES + 1)*controller->target_size*i_p_ratio/(1+NB_P_FRAMES*i_p_ratio);
419 if ((controller->blockline+1) == controller->num_blockline)
422 if ((target_size > stream->used) && controller->quant > 1)
424 // last frame was too small increase overall quality (i.e. decrease quant)
427 else if ((target_size < stream->used) && controller->quant < 51)
429 // last frame was too large decrease overall quality (i.e. increase quant)
433 // update las_x_size infos
434 if (controller->picture_type == VIDEO_PICTURE_INTRA)
436 ((p264_codec_t*)video_codec)->last_I_size = stream->used;
440 ((p264_codec_t*)video_codec)->last_P_size = stream->used;
445 controller->quant= P264_DEFAULT_QUANTIZATION;
447 RTMON_USTOP(VIDEO_VLIB_PACKET);
450 if( controller->picture_complete )
452 video_stuff8( stream );
453 video_write_data( stream, PICTURE_END_CODE, 22 );
456 // Update controller according to user inputs & video statistics
457 video_controller_update( controller, picture_complete );
462 #ifndef HAS_P264_DECODE_BLOCKLINE
463 C_RESULT p264_decode_blockline( video_controller_t* controller, vp_api_picture_t* picture, bool_t* got_image )
465 p264_codec_t* video_codec;
466 vp_api_picture_t blockline = { 0 };
467 int32_t num_macro_blocks = 0;
468 video_macroblock_t* macroblock = NULL;
469 MB_p264_t* p264_mb = NULL;
470 video_picture_context_t blockline_ctx;
471 video_picture_context_t blockline_src;
473 uint32_t x_luma=0,y_luma=0;
474 uint32_t x_chroma=0,y_chroma=0;
476 controller->mode = VIDEO_DECODE;
477 video_codec = (p264_codec_t*)controller->video_codec;
479 blockline = *picture;
480 blockline.height = MB_HEIGHT_Y;
481 blockline.complete = 1;
482 blockline.vision_complete = 0;
484 picture->complete = controller->picture_complete;
486 blockline_ctx.y_woffset = blockline.y_line_size;
487 blockline_ctx.c_woffset = blockline.cb_line_size;
488 blockline_ctx.y_hoffset = blockline.y_line_size * MCU_HEIGHT;
490 // At least a complete blockline is found
491 while( !controller->picture_complete && controller->in_stream.index <= (controller->in_stream.used >> 2) )
493 p264_unpack_controller( controller );
494 // update controller picture type
495 controller->picture_type = video_codec->picture_layer.picture_type;
497 if( !controller->picture_complete )
499 blockline.blockline = controller->blockline;
501 blockline_ctx.y_src = picture->y_buf + blockline.blockline * MB_HEIGHT_Y * picture->y_line_size;
502 blockline_ctx.cb_src = picture->cb_buf + blockline.blockline * MB_HEIGHT_C * picture->cb_line_size;
503 blockline_ctx.cr_src = picture->cr_buf + blockline.blockline * MB_HEIGHT_C * picture->cr_line_size;
505 picture->blockline = controller->blockline;
506 num_macro_blocks = controller->mb_blockline;
508 gobs = &controller->gobs[controller->blockline];
509 // contrairement a UVLC, macroblock pointe dans le cache et non pas dans le cache_mbs
510 macroblock = gobs->macroblocks;
512 if( gobs->quant != controller->quant )
514 controller->quant = gobs->quant;
515 video_quantizer_update( controller );
518 // compute luma/chroma block (x,y) destination
520 y_luma = blockline.blockline * MB_HEIGHT_Y;
522 y_chroma = blockline.blockline * MB_HEIGHT_C;
524 while( num_macro_blocks > 0 )
526 p264_mb = (MB_p264_t*)macroblock->data;
528 p264_read_mb_layer(controller, &controller->in_stream, controller->gobs, controller->blockline, controller->mb_blockline-num_macro_blocks);
530 if (controller->picture_type == VIDEO_PICTURE_INTER)
532 video_p264_decode_inter_luma_MB ( video_codec->ref_picture.y_buf,
533 video_codec->decoded_picture.y_buf,
535 video_codec->decoded_picture.width, video_codec->decoded_picture.height,
536 video_codec->decoded_picture.y_line_size,
537 macroblock->inter_MV,
538 macroblock->inter_partition_mode,
539 macroblock->nb_partition,
543 video_p264_decode_inter_chroma_MB ( video_codec->ref_picture.cb_buf,
544 video_codec->decoded_picture.cb_buf,
546 video_codec->decoded_picture.width>>1, video_codec->decoded_picture.height>>1,
547 video_codec->decoded_picture.cb_line_size,
548 macroblock->inter_MV,
549 macroblock->inter_partition_mode,
550 macroblock->nb_partition,
555 video_p264_decode_inter_chroma_MB ( video_codec->ref_picture.cr_buf,
556 video_codec->decoded_picture.cr_buf,
558 video_codec->decoded_picture.width>>1, video_codec->decoded_picture.height>>1,
559 video_codec->decoded_picture.cr_line_size,
560 macroblock->inter_MV,
561 macroblock->inter_partition_mode,
562 macroblock->nb_partition,
567 else if (macroblock->intra_type == INTRA_4x4)
569 video_p264_decode_intra_luma_4x4_MB (p264_mb->intra_4x4.AC_Y,
570 video_codec->decoded_picture.y_buf, video_codec->decoded_picture.width,
571 x_luma, y_luma, video_codec->decoded_picture.y_line_size,
572 macroblock->intra_4x4_mode,
575 video_p264_decode_intra_chroma_8x8_MB (p264_mb->intra_4x4.DC_U,
576 p264_mb->intra_4x4.AC_U,
577 video_codec->decoded_picture.cb_buf,
578 x_chroma, y_chroma, video_codec->decoded_picture.cb_line_size,
579 macroblock->intra_chroma_8x8_mode,
582 video_p264_decode_intra_chroma_8x8_MB (p264_mb->intra_4x4.DC_V,
583 p264_mb->intra_4x4.AC_V,
584 video_codec->decoded_picture.cr_buf,
585 x_chroma, y_chroma, video_codec->decoded_picture.cr_line_size,
586 macroblock->intra_chroma_8x8_mode,
591 video_p264_decode_intra_luma_16x16_MB (p264_mb->intra_16x16.DC_Y,
592 p264_mb->intra_16x16.AC_Y,
593 video_codec->decoded_picture.y_buf,
594 x_luma, y_luma, video_codec->decoded_picture.y_line_size,
595 macroblock->intra_luma_16x16_mode,
598 video_p264_decode_intra_chroma_8x8_MB (p264_mb->intra_16x16.DC_U,
599 p264_mb->intra_16x16.AC_U,
600 video_codec->decoded_picture.cb_buf,
601 x_chroma, y_chroma, video_codec->decoded_picture.cb_line_size,
602 macroblock->intra_chroma_8x8_mode,
605 video_p264_decode_intra_chroma_8x8_MB (p264_mb->intra_16x16.DC_V,
606 p264_mb->intra_16x16.AC_V,
607 video_codec->decoded_picture.cr_buf,
608 x_chroma, y_chroma, video_codec->decoded_picture.cr_line_size,
609 macroblock->intra_chroma_8x8_mode,
613 // compute next block coordinates
614 x_luma += MB_HEIGHT_Y;
615 x_chroma += MB_HEIGHT_C;
620 // prepare the source picture context
621 blockline_src.y_woffset = video_codec->decoded_picture.y_line_size;
622 blockline_src.c_woffset = video_codec->decoded_picture.cb_line_size;
623 blockline_src.y_hoffset = video_codec->decoded_picture.y_line_size * MCU_HEIGHT;
624 blockline_src.y_src = video_codec->decoded_picture.y_buf + blockline.blockline * MB_HEIGHT_Y * video_codec->decoded_picture.y_line_size;
625 blockline_src.cb_src = video_codec->decoded_picture.cb_buf + blockline.blockline * MB_HEIGHT_C * video_codec->decoded_picture.cb_line_size;
626 blockline_src.cr_src = video_codec->decoded_picture.cr_buf + blockline.blockline * MB_HEIGHT_C * video_codec->decoded_picture.cr_line_size;
627 // convert src to dest
628 video_blockline_from_blockline(&blockline_ctx, &blockline_src, controller->mb_blockline, picture->format);
630 // Update controller according to video statistics
631 video_controller_update( controller, controller->picture_complete );
635 if( controller->picture_complete )
637 picture->complete = controller->picture_complete;
638 picture->blockline = 0;
640 controller->picture_complete = 0;
641 controller->in_stream.length = 32;
642 controller->num_frames++;
648 controller->in_stream.used = 0;
649 controller->in_stream.index = 0;
656 C_RESULT p264_update( video_controller_t* controller )
661 C_RESULT p264_cache( video_controller_t* controller, video_stream_t* ex_stream)
665 video_stream_t* in_stream = &controller->in_stream;
667 switch( controller->mode )
670 res = p264_flush_stream( ex_stream, in_stream );
674 res = p264_load_stream( in_stream, ex_stream );