ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VLIB / video_codec.c
diff --git a/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/video_codec.c b/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/video_codec.c
new file mode 100644 (file)
index 0000000..94fec70
--- /dev/null
@@ -0,0 +1,260 @@
+#include <VLIB/video_codec.h>
+#include <VLIB/video_quantizer.h>
+#include <VLIB/video_packetizer.h>
+#include <VLIB/Platform/video_utils.h>
+#include <VLIB/Platform/video_config.h>
+
+#include <VP_Os/vp_os_malloc.h>
+#include <VP_Os/vp_os_print.h>
+
+#ifdef _ELINUX
+#include "dma_malloc.h"
+#define vp_os_aligned_malloc(A,B) dma_malloc(A)
+#define vp_os_aligned_free(A) dma_free(A)
+#endif
+
+extern C_RESULT video_utils_init( video_controller_t* controller );
+extern C_RESULT video_utils_close( video_controller_t* controller );
+
+extern void uvlc_codec_alloc( video_controller_t* controller );
+extern void uvlc_codec_free( video_controller_t* controller );
+
+extern void p263_codec_alloc( video_controller_t* controller );
+extern void p263_codec_free( video_controller_t* controller );
+
+extern void p264_codec_alloc( video_controller_t* controller );
+extern void p264_codec_free( video_controller_t* controller );
+
+static C_RESULT video_codec_open_private( video_controller_t* controller, codec_type_t codec_type, bool_t keep_stream );
+static C_RESULT video_codec_close_private( video_controller_t* controller, bool_t keep_stream );
+
+static C_RESULT video_codec_open_private( video_controller_t* controller, codec_type_t codec_type, bool_t keep_stream )
+{
+  C_RESULT res;
+  // Data used to initialize macroblock's cache
+  int32_t i;
+  int16_t* cache;
+  video_macroblock_t* mb;
+
+  // Close any previously allocated codec for this controller
+  video_codec_close_private( controller, keep_stream);
+
+  controller->mode            = 0;
+  controller->use_me          = FALSE;
+  controller->do_azq          = FALSE;
+  controller->aq              = 0;
+  controller->bq              = 0;
+  controller->target_bitrate  = VLIB_DEFAULT_BITRATE;
+  controller->num_frames      = 0;
+  controller->picture_type    = 0;
+  controller->width           = 0;
+  controller->height          = 0;
+  controller->resolution_changed = FALSE;
+  controller->num_blockline   = 0;
+  controller->mb_blockline    = 0;
+  controller->blockline       = 0;
+  controller->picture_complete= 0;
+  controller->quant           = DEFAULT_QUANTIZATION;
+  controller->dquant          = 0;
+  controller->Qp              = 0;
+  controller->invQp           = 1;
+  controller->gobs            = NULL;
+  controller->cache           = NULL;
+  controller->codec_type      = 0;
+  controller->video_codec     = NULL;
+
+  if( controller->blockline_cache == NULL )
+  {
+    // We alloc two buffers to be compatible with an asynchronous DCT
+    // When a DCT will be performed on one buffer, we will be able to use the other for caching or computing purpose
+    // DCT_BUFFER_SIZE = MAX_NUM_MACRO_BLOCKS_PER_CALL * 6 * MCU_BLOCK_SIZE
+    controller->blockline_cache = (int16_t*)vp_os_aligned_malloc( 2*DCT_BUFFER_SIZE*sizeof(int16_t), VLIB_ALLOC_ALIGN );
+  }
+  if (controller->cache_mbs == NULL)
+  {
+    controller->cache_mbs = vp_os_malloc( 2 * MAX_NUM_MACRO_BLOCKS_PER_CALL * sizeof(video_macroblock_t) );
+    mb = &controller->cache_mbs[0];
+    cache = controller->blockline_cache;
+    for(i = 2*MAX_NUM_MACRO_BLOCKS_PER_CALL; i > 0; i-- )
+    {
+      mb->data = cache;
+      cache   += MCU_BLOCK_SIZE*6;
+      mb ++;
+    }
+  }
+
+  if (keep_stream == FALSE)
+    video_packetizer_init( controller );
+  video_quantizer_init( controller );
+
+  switch( codec_type )
+  {
+    case UVLC_CODEC:
+      uvlc_codec_alloc( controller );
+      break;
+
+    case P263_CODEC:
+      p263_codec_alloc( controller );
+      break;
+
+    case P264_CODEC:
+      p264_codec_alloc( controller );
+      break;
+
+    default:
+      controller->video_codec = NULL;
+      break;
+  }
+
+  if( controller->video_codec != NULL )
+  {
+    controller->codec_type = codec_type;
+    res = C_OK;
+  }
+  else
+  {
+    res = C_FAIL;
+  }
+
+  video_utils_init( controller );
+
+  return res;
+}
+
+C_RESULT video_codec_open( video_controller_t* controller, codec_type_t codec_type )
+{
+  return video_codec_open_private(controller, codec_type, FALSE );
+}
+
+static C_RESULT video_codec_close_private( video_controller_t* controller, bool_t keep_stream )
+{
+  video_utils_close( controller );
+
+  if( controller->blockline_cache != NULL )
+  {
+    vp_os_aligned_free( controller->blockline_cache );
+    controller->blockline_cache = NULL;
+  }
+
+  if (controller->cache_mbs != NULL)
+  {
+    vp_os_free( controller->cache_mbs );
+    controller->cache_mbs = NULL;
+  }
+
+
+  if( keep_stream == FALSE && controller->in_stream.bytes != NULL )
+    video_packetizer_close( controller );
+
+  switch( controller->codec_type )
+  {
+    case UVLC_CODEC:
+      uvlc_codec_free( controller );
+      break;
+
+    case P263_CODEC:
+      p263_codec_free( controller );
+      break;
+
+    case P264_CODEC:
+      p264_codec_free( controller );
+      break;
+
+    default:
+      break;
+  }
+
+  // Cleanup caches
+  video_controller_cleanup( controller );
+
+  return C_OK;
+}
+
+C_RESULT video_codec_close ( video_controller_t* controller)
+{
+  return video_codec_close_private(controller, FALSE);
+}
+
+C_RESULT video_codec_type_select(video_controller_t* controller, video_stream_t* stream)
+{
+   uint32_t codec_type = 0;
+   video_align8( stream );
+   video_peek_data( stream, &codec_type, 22 );
+   // extract codec tag
+   //codec_type = codec_type>>5;
+
+   if (codec_type != controller->codec_type)
+   {
+     PRINT("VLIB new codec %d\n",codec_type);
+     // video codec has changed, load a new codec
+     video_codec_open_private( controller, codec_type, TRUE );
+
+   }
+   return C_OK;
+}
+
+C_RESULT video_encode_picture( video_controller_t* controller, const vp_api_picture_t* picture, bool_t* got_image )
+{
+  vp_api_picture_t blockline = { 0 };
+
+  controller->mode  = VIDEO_ENCODE;
+
+  video_controller_set_format( controller, picture->width, picture->height );
+
+  blockline                   = *picture;
+  blockline.height            = MB_HEIGHT_Y;
+  blockline.complete          = 1;
+  blockline.vision_complete   = 0;
+
+  // Reset internal stream for new blockline/picture
+  controller->in_stream.used  = 0;
+  controller->in_stream.index = 0;
+
+  while( !controller->picture_complete )
+  {
+    video_encode_blockline( controller, &blockline, blockline.blockline == (controller->num_blockline-1) );
+
+    blockline.y_buf  += MB_HEIGHT_Y * picture->y_line_size;
+    blockline.cb_buf += MB_HEIGHT_C * picture->cb_line_size;
+    blockline.cr_buf += MB_HEIGHT_C * picture->cr_line_size;
+
+    blockline.blockline++;
+  }
+
+  if( picture->complete )
+  {
+    video_write_data( &controller->in_stream, 0, controller->in_stream.length+1 );
+    controller->in_stream.length = 32;
+    controller->picture_complete = 0;
+    *got_image = TRUE;
+  }
+
+  return C_OK;
+}
+
+C_RESULT video_decode_picture( video_controller_t* controller, vp_api_picture_t* picture, video_stream_t* ex_stream, bool_t* got_image )
+{
+  vp_api_picture_t blockline = { 0 };
+
+  controller->mode  = VIDEO_DECODE; // mandatory because of video_cache_stream
+
+  blockline                   = *picture;
+  blockline.height            = MB_HEIGHT_Y;
+  blockline.complete          = 1;
+  blockline.vision_complete   = 0;
+
+  while( VP_SUCCEEDED(video_cache_stream( controller, ex_stream )) )
+  {
+    video_codec_type_select(controller,ex_stream); // to be verified
+    video_decode_blockline( controller, &blockline, got_image );
+  }
+
+  return C_OK;
+}
+
+
+C_RESULT video_decode_blockline( video_controller_t* controller, vp_api_picture_t* blockline, bool_t* got_image )
+{
+  video_codec_type_select(controller,&controller->in_stream);
+  return controller->video_codec->decode_blockline( controller, blockline, got_image );
+}