videoeditorengine/avcedit/src/parameterset.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/avcedit/src/parameterset.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,2403 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:
+*
+*/
+
+
+#include <string.h>
+#include "globals.h"
+#include "vld.h"
+#include "parameterset.h"
+
+
+#define MIN_CHROMA_QP_INDEX           -12
+#define MAX_CHROMA_QP_INDEX            12
+#define NUM_LEVELS                     16     /* The number of AVC levels */
+#define MAX_PIC_SIZE_IN_MBS            36864
+#define MAX_PIC_WIDTH_IN_MBS           543    /* Sqrt( MAX_PIC_SIZE_IN_MBS * 8 ) */
+#define MAX_PIC_HEIGHT_IN_MBS          543    /* Sqrt( MAX_PIC_SIZE_IN_MBS * 8 ) */
+
+
+/* These fields are defined in Annex A of the standard */
+typedef struct _level_s 
+{
+  int8 levelNumber;
+  int8 constraintSet3flag;
+  int32 maxMBPS;
+  int32 maxFS;
+  int32 maxDPB;
+  int32 maxBR;
+  int32 maxCPB;
+  int16 maxVmvR;
+  int8 minCR;
+  int8 maxMvsPer2Mb;
+} level_s;
+
+/* Parameters for all levels */
+static const level_s levelArray[NUM_LEVELS] = {
+  {10, 0,   1485,    99,   152064,     64,    175,  64, 2, 32},
+  {11, 1,   1485,    99,   152064,    128,    350,  64, 2, 32}, /* level 1b */
+  {11, 0,   3000,   396,   345600,    192,    500, 128, 2, 32},
+  {12, 0,   6000,   396,   912384,    384,   1000, 128, 2, 32},
+  {13, 0,  11880,   396,   912384,    768,   2000, 128, 2, 32},
+  {20, 0,  11880,   396,   912384,   2000,   2000, 128, 2, 32},
+  {21, 0,  19800,   792,  1824768,   4000,   4000, 256, 2, 32},
+  {22, 0,  20250,  1620,  3110400,   4000,   4000, 256, 2, 32},
+  {30, 0,  40500,  1620,  3110400,  10000,  10000, 256, 2, 32},
+  {31, 0, 108000,  3600,  6912000,  14000,  14000, 512, 4, 16},
+  {32, 0, 216000,  5120,  7864320,  20000,  20000, 512, 4, 16},
+  {40, 0, 245760,  8192, 12582912,  20000,  25000, 512, 4, 16},
+  {41, 0, 245760,  8192, 12582912,  50000,  62500, 512, 2, 16},
+  {42, 0, 491520,  8192, 12582912,  50000,  62500, 512, 2, 16},
+  {50, 0, 589824, 22080, 42393600, 135000, 135000, 512, 2, 16},
+  {51, 0, 983040, 36864, 70778880, 240000, 240000, 512, 2, 16}
+};
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+
+struct aspectRatio_s 
+{
+  int width;
+  int height;
+};
+
+static const struct aspectRatio_s aspectRatioArr[13] = 
+{
+  {  1,  1},
+  { 12, 11},
+  { 10, 11},
+  { 16, 11},
+  { 40, 33},
+  { 24, 11},
+  { 20, 11},
+  { 32, 11},
+  { 80, 33},
+  { 18, 11},
+  { 15, 11},
+  { 64, 33},
+  {160, 99}
+};
+#endif  // VIDEOEDITORENGINE_AVC_EDITING
+
+/*
+ * AVC syntax functions as specified in specification
+ */
+
+/* Return fixed length code */
+static int u_n(bitbuffer_s *bitbuf, int len, unsigned int *val)
+{
+  *val = vldGetFLC(bitbuf, len);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return PS_ERROR;
+
+  return PS_OK;
+}
+
+/* Return unsigned UVLC code */
+static int ue_v(bitbuffer_s *bitbuf, unsigned int *val, unsigned int maxVal)
+{
+  *val = vldGetUVLC(bitbuf);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return PS_ERROR;
+
+  if (*val > maxVal)
+    return PS_ERR_ILLEGAL_VALUE;
+
+  return PS_OK;
+}
+
+/* Return long signed UVLC code */
+static int se_v_long(bitbuffer_s *bitbuf, int32 *val)
+{
+  *val = vldGetSignedUVLClong(bitbuf);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return PS_ERROR;
+
+  return PS_OK;
+}
+
+/* Return long unsigned UVLC code */
+static int ue_v_long(bitbuffer_s *bitbuf, u_int32 *val, u_int32 maxVal)
+{
+  *val = vldGetUVLClong(bitbuf);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return PS_ERROR;
+
+  if (*val > maxVal)
+    return PS_ERR_ILLEGAL_VALUE;
+
+  return PS_OK;
+}
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+
+/* Return signed UVLC code */
+static int se_v(bitbuffer_s *bitbuf, int *val, int minVal, int maxVal)
+{
+  *val = vldGetSignedUVLC(bitbuf);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return PS_ERROR;
+
+  if (*val < minVal || *val > maxVal)
+    return PS_ERR_ILLEGAL_VALUE;
+
+  return PS_OK;
+}
+
+#endif  // VIDEOEDITORENGINE_AVC_EDITING
+
+
+/*
+ * getLevel:
+ *
+ * Parameters:
+ *      levelNumber
+ *      constraintSet3flag
+ *
+ * Function:
+ *      Return parameters for level based on level number.
+ *
+ *  Return:
+ *      Pointer to level or 0 if level does not exist
+ */
+static const level_s *getLevel(int levelNumber, int constraintSet3flag)
+{
+  int i;
+
+  for (i = 0; i < NUM_LEVELS; i++) {
+    if (levelArray[i].levelNumber == levelNumber &&
+        levelArray[i].constraintSet3flag == constraintSet3flag)
+      return &levelArray[i];
+  }
+
+  PRINT((_L("Unknown level: %i.\n"), levelNumber));            
+  return 0;
+}
+
+/*
+ *
+ * getHrdParameters:
+ *
+ * Parameters:
+ *      bitbuf                The bitbuffer object
+ *      hrd                   the pointer for returning HRD parameters
+ *
+ * Function:
+ *      decode the HRD Parameters
+ *
+ * Returns:
+ *      PS_OK:                Hrd parameters decoded succesfully
+ *      <0:                   Fail
+ */
+static int getHrdParameters(bitbuffer_s *bitbuf, hrd_parameters_s *hrd)
+{
+  unsigned int i;
+  int retCode;
+
+  if ((retCode = ue_v(bitbuf, &hrd->cpb_cnt_minus1, 31)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 4, &hrd->bit_rate_scale)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 4, &hrd->cpb_size_scale)) < 0)
+    return retCode;
+
+  for (i = 0; i <= hrd->cpb_cnt_minus1; i++) {
+    /* bit_rate_value_minus1 must be in range of 0 to 2^32-2 */
+    if ((retCode = ue_v_long(bitbuf, &hrd->bit_rate_value_minus1[i], (u_int32)4294967294U)) < 0)
+      return retCode;
+
+    /* cpb_size_value_minus1 must be in range of 0 to 2^32-2 */
+    if ((retCode = ue_v_long(bitbuf, &hrd->cpb_size_value_minus1[i], (u_int32)4294967294U)) < 0)
+      return retCode;
+
+    if ((retCode = u_n(bitbuf, 1, &hrd->cbr_flag[i])) < 0)
+      return retCode;
+  }
+
+  if ((retCode = u_n(bitbuf, 5, &hrd->initial_cpb_removal_delay_length_minus1)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 5, &hrd->cpb_removal_delay_length_minus1)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 5, &hrd->dpb_output_delay_length_minus1)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 5, &hrd->time_offset_length)) < 0)
+    return retCode;
+
+  return PS_OK;
+}
+
+
+
+/*
+ *
+ * getVUI:
+ *
+ * Parameters:
+ *      bitbuf                The bitbuffer object
+ *      vui                   the pointer for returning VUI parameters
+ *
+ * Function:
+ *      decode the VUI Parameters
+ *
+ * Returns:
+ *      PS_OK:                VUI parameters decoded succesfully
+ *      <0:                   Fail
+ */
+static int getVUI(bitbuffer_s *bitbuf, vui_parameters_s *vui)
+{
+  unsigned tempWordHi, tempWordLo;
+  int retCode;
+
+  if ((retCode = u_n(bitbuf, 1, &vui->aspect_ratio_info_present_flag)) < 0)
+    return retCode;
+
+  if (vui->aspect_ratio_info_present_flag) {
+    if ((retCode = u_n(bitbuf, 8, &vui->aspect_ratio_idc)) < 0)
+      return retCode;
+    if (vui->aspect_ratio_idc == PS_EXTENDED_SAR) {
+      if ((retCode = u_n(bitbuf, 16, &vui->sar_width)) < 0)
+        return retCode;
+      if ((retCode = u_n(bitbuf, 16, &vui->sar_height)) < 0)
+        return retCode;
+    }
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &vui->overscan_info_present_flag)) < 0)
+    return retCode;
+
+  if (vui->overscan_info_present_flag) {
+    if ((retCode = u_n(bitbuf, 1, &vui->overscan_appropriate_flag)) < 0)
+      return retCode;
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &vui->video_signal_type_present_flag)) < 0)
+    return retCode;
+
+  if (vui->video_signal_type_present_flag) {
+    if ((retCode = u_n(bitbuf, 3, &vui->video_format)) < 0)
+      return retCode;
+    if ((retCode = u_n(bitbuf, 1, &vui->video_full_range_flag)) < 0)
+      return retCode;
+    if ((retCode = u_n(bitbuf, 1, &vui->colour_description_present_flag)) < 0)
+      return retCode;
+    if (vui->colour_description_present_flag) {
+      if ((retCode = u_n(bitbuf, 8, &vui->colour_primaries)) < 0)
+        return retCode;
+      if ((retCode = u_n(bitbuf, 8, &vui->transfer_characteristics)) < 0)
+        return retCode;
+      if ((retCode = u_n(bitbuf, 8, &vui->matrix_coefficients)) < 0)
+        return retCode;
+    }
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &vui->chroma_loc_info_present_flag)) < 0)
+    return retCode;
+
+  if (vui->chroma_loc_info_present_flag) {
+    if ((retCode = ue_v(bitbuf, &vui->chroma_sample_loc_type_top_field, 5)) < 0)
+      return retCode;
+    if ((retCode = ue_v(bitbuf, &vui->chroma_sample_loc_type_bottom_field, 5)) < 0)
+      return retCode;
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &vui->timing_info_present_flag)) < 0)
+    return retCode;
+
+  if (vui->timing_info_present_flag) {
+    if ((retCode = u_n(bitbuf, 16, &tempWordHi)) < 0)
+      return retCode;
+    if ((retCode = u_n(bitbuf, 16, &tempWordLo)) < 0)
+      return retCode;
+    vui->num_units_in_tick = (((u_int32)tempWordHi) << 16) | ((u_int32)tempWordLo);
+
+    if ((retCode = u_n(bitbuf, 16, &tempWordHi)) < 0)
+      return retCode;
+    if ((retCode = u_n(bitbuf, 16, &tempWordLo)) < 0)
+      return retCode;
+    vui->time_scale = (((u_int32)tempWordHi) << 16) | ((u_int32)tempWordLo);
+
+    if ((retCode = u_n(bitbuf, 1, &vui->fixed_frame_rate_flag)) < 0)
+      return retCode;
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &vui->nal_hrd_parameters_present_flag)) < 0)
+    return retCode;
+
+  if (vui->nal_hrd_parameters_present_flag) {
+    if ((retCode = getHrdParameters(bitbuf, &vui->nal_hrd_parameters)) < 0)
+      return retCode;
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &vui->vcl_hrd_parameters_present_flag)) < 0)
+    return retCode;
+
+  if (vui->vcl_hrd_parameters_present_flag) {
+    if ((retCode = getHrdParameters(bitbuf, &vui->vcl_hrd_parameters)) < 0)
+      return retCode;
+  }
+
+  if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag) {
+    if ((retCode = u_n(bitbuf, 1, &vui->low_delay_hrd_flag)) < 0)
+      return retCode;
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &vui->pic_struct_present_flag)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 1, &vui->bitstream_restriction_flag)) < 0)
+    return retCode;
+
+  if (vui->bitstream_restriction_flag) {
+    if ((retCode = u_n(bitbuf, 1, &vui->motion_vectors_over_pic_boundaries_flag)) < 0)
+      return retCode;
+    if ((retCode = ue_v(bitbuf, &vui->max_bytes_per_pic_denom, 16)) < 0)
+      return retCode;
+    if ((retCode = ue_v(bitbuf, &vui->max_bits_per_mb_denom, 16)) < 0)
+      return retCode;
+    if ((retCode = ue_v(bitbuf, &vui->log2_max_mv_length_horizontal, 16)) < 0)
+      return retCode;
+    if ((retCode = ue_v(bitbuf, &vui->log2_max_mv_length_vertical, 16)) < 0)
+      return retCode;
+    if ((retCode = ue_v(bitbuf, &vui->num_reorder_frames, 16)) < 0)
+      return retCode;
+    if ((retCode = ue_v(bitbuf, &vui->max_dec_frame_buffering, 16)) < 0)
+      return retCode;
+  }
+
+  return PS_OK;
+}
+
+
+/*
+ *
+ * setVUIdefaults:
+ *
+ * Parameters:
+ *      vui                   Pointer to VUI parameters
+ *
+ * Function:
+ *      Set VUI parameters to their default values when default value is non-zero.
+ *
+ * Returns:
+ *      -
+ */
+static void setVUIdefaults(seq_parameter_set_s *sps)
+{
+  vui_parameters_s *vui;
+  const level_s *level;
+  int MaxDpbSize;
+
+  vui = &sps->vui_parameters;
+
+  vui->video_format                            = 5;
+  vui->colour_primaries                        = 2;
+  vui->transfer_characteristics                = 2;
+  vui->matrix_coefficients                     = 2;
+  vui->motion_vectors_over_pic_boundaries_flag = 1;
+  vui->max_bytes_per_pic_denom                 = 2;
+  vui->max_bits_per_mb_denom                   = 1;
+  vui->log2_max_mv_length_horizontal           = 16;
+  vui->log2_max_mv_length_vertical             = 16;
+
+  level = getLevel(sps->level_idc, sps->constraint_set3_flag);
+  MaxDpbSize = level->maxDPB /
+    ((sps->pic_width_in_mbs_minus1+1) * (sps->pic_height_in_map_units_minus1+1) * 384);
+  MaxDpbSize = clip(1, 16, MaxDpbSize);
+
+  vui->max_dec_frame_buffering = MaxDpbSize;
+  vui->num_reorder_frames      = vui->max_dec_frame_buffering;
+}
+
+/*
+ *
+ * psDecodeSPS:
+ *      
+ * Parameters:
+ *      bitbuf                Bitbuffer object
+ *      spsList               The list for SPS's, the newly decoded SPS will be stored into the list
+ *
+ * Function:
+ *      Decode the SPS, and store it into the SPS list
+ *
+ * Returns:
+ *      PS_OK:                SPS decoded succesfully
+ *      <0:                   Fail
+ */
+int psDecodeSPS( bitbuffer_s *bitbuf, seq_parameter_set_s **spsList, 
+                 TInt& aWidth, TInt& aHeight )
+{
+  seq_parameter_set_s *sps;
+  unsigned int i;
+  int retCode;
+
+  unsigned  profile_idc;                                      // u(8)
+  Boolean   constraint_set0_flag;                             // u(1)
+  Boolean   constraint_set1_flag;                             // u(1)
+  Boolean   constraint_set2_flag;                             // u(1)
+  Boolean   constraint_set3_flag;                             // u(1)
+  Boolean   reserved_zero_4bits;                              // u(4)
+  unsigned  level_idc;                                        // u(8)
+  unsigned  seq_parameter_set_id;                             // ue(v)
+
+
+  /*
+   * Parse sequence parameter set syntax until sps id
+   */
+
+  if ((retCode = u_n(bitbuf, 8, &profile_idc)) < 0)
+    return retCode;
+
+  /* If constraint_set0_flag == 1, stream is Baseline Profile compliant */
+  if ((retCode = u_n(bitbuf, 1, &constraint_set0_flag)) < 0)
+    return retCode;
+
+  /* If constraint_set1_flag == 1, stream is Main Profile compliant */
+  if ((retCode = u_n(bitbuf, 1, &constraint_set1_flag)) < 0)
+    return retCode;
+
+  /* If constraint_set2_flag == 1, stream is Extended Profile compliant */
+  if ((retCode = u_n(bitbuf, 1, &constraint_set2_flag)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 1, &constraint_set3_flag)) < 0)
+    return retCode;
+
+  /* If CABAC is not defined we support only baseline compliant streams */
+#ifndef ENABLE_CABAC
+  if (profile_idc != PS_BASELINE_PROFILE_IDC && constraint_set0_flag == 0)
+    return PS_ERR_UNSUPPORTED_PROFILE;
+#else
+  if (profile_idc != PS_BASELINE_PROFILE_IDC && constraint_set0_flag == 0 &&
+      profile_idc != PS_MAIN_PROFILE_IDC && constraint_set1_flag == 0)
+    return PS_ERR_UNSUPPORTED_PROFILE;
+#endif
+
+  /* We don't care what is in these bits */
+  if ((retCode = u_n(bitbuf, 4, &reserved_zero_4bits)) < 0)
+    return retCode;
+
+  /* Fetch level */
+  if ((retCode = u_n(bitbuf, 8, &level_idc)) < 0)
+    return retCode;
+
+  /* Find level in the list of legal levels */
+  for (i = 0; i < NUM_LEVELS; i++) {
+    if ((int)level_idc == levelArray[i].levelNumber)
+      break;
+  }
+
+  /* If level was not found in the list, return with error */
+  if (i == NUM_LEVELS)
+    return PS_ERR_ILLEGAL_VALUE;
+
+  /* Get sequence parameter set id */
+  if ((retCode = ue_v(bitbuf, &seq_parameter_set_id, PS_MAX_NUM_OF_SPS-1)) < 0)
+    return retCode;
+
+
+  /*
+   * Allocate memory for SPS
+   */
+
+  /* Pointer to sequence parameter set structure */
+  sps = spsList[seq_parameter_set_id];
+
+  /* allocate mem for SPS, if it has not been allocated already */
+  if (!sps) {
+    sps = (seq_parameter_set_s *) User::Alloc(sizeof(seq_parameter_set_s));    
+    if (sps == 0) {
+      return PS_ERR_MEM_ALLOC;
+    }
+    memset( sps, 0, sizeof(seq_parameter_set_s));
+    spsList[seq_parameter_set_id] = sps;
+  }
+
+
+  /* Copy temporary variables to sequence parameter set structure */
+  sps->profile_idc          = profile_idc;
+  sps->constraint_set0_flag = constraint_set0_flag;
+  sps->constraint_set1_flag = constraint_set1_flag;
+  sps->constraint_set2_flag = constraint_set2_flag;
+  sps->constraint_set3_flag = constraint_set3_flag;
+  sps->reserved_zero_4bits  = reserved_zero_4bits;
+  sps->level_idc            = level_idc;
+  sps->seq_parameter_set_id = seq_parameter_set_id;
+
+
+  /*
+   * Parse rest of the sequence parameter set syntax
+   */
+
+  /* This defines how many bits there are in frame_num syntax element */
+  if ((retCode = ue_v(bitbuf, &sps->log2_max_frame_num_minus4, 12)) < 0)
+    return retCode;
+
+  /* Fetch POC type */
+  if ((retCode = ue_v(bitbuf, &sps->pic_order_cnt_type, 2)) < 0)
+    return retCode;
+
+  if (sps->pic_order_cnt_type == 0) {
+    if ((retCode = ue_v(bitbuf, &sps->log2_max_pic_order_cnt_lsb_minus4, 12)) < 0)
+      return retCode;
+  }
+  else if (sps->pic_order_cnt_type == 1) {
+    if ((retCode = u_n(bitbuf, 1, &sps->delta_pic_order_always_zero_flag)) < 0)
+      return retCode;
+
+    if ((retCode = se_v_long(bitbuf, &sps->offset_for_non_ref_pic)) < 0)
+      return retCode;
+
+    if ((retCode = se_v_long(bitbuf, &sps->offset_for_top_to_bottom_field)) < 0)
+      return retCode;
+
+    if ((retCode = ue_v(bitbuf, &sps->num_ref_frames_in_pic_order_cnt_cycle, 255)) < 0)
+      return retCode;
+
+    for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) {
+      if ((retCode = se_v_long(bitbuf, &sps->offset_for_ref_frame[i])) < 0)
+        return retCode;
+    }
+  }
+
+  if ((retCode = ue_v(bitbuf, &sps->num_ref_frames, 16)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 1, &sps->gaps_in_frame_num_value_allowed_flag)) < 0)
+    return retCode;
+
+  if ((retCode = ue_v(bitbuf, &sps->pic_width_in_mbs_minus1, MAX_PIC_WIDTH_IN_MBS-1)) < 0)
+    return retCode;
+  
+  aWidth = (sps->pic_width_in_mbs_minus1 + 1) * 16;
+
+  if ((retCode = ue_v(bitbuf, &sps->pic_height_in_map_units_minus1, MAX_PIC_WIDTH_IN_MBS-1)) < 0)
+    return retCode;
+  
+  aHeight = (sps->pic_height_in_map_units_minus1 + 1) * 16;
+
+  if ((retCode = u_n(bitbuf, 1, &sps->frame_mbs_only_flag)) < 0)
+    return retCode;
+
+  if (!sps->frame_mbs_only_flag) {
+    // u_n(bitbuf, 1, &sps->mb_adaptive_frame_field_flag);
+    return PS_ERR_UNSUPPORTED_FEATURE;
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &sps->direct_8x8_inference_flag)) < 0)
+    return retCode;
+
+  if ((retCode = u_n(bitbuf, 1, &sps->frame_cropping_flag)) < 0)
+    return retCode;
+
+  /* Fetch cropping window */
+  if (sps->frame_cropping_flag) {
+    if ((retCode = ue_v(bitbuf, &sps->frame_crop_left_offset, 8*(sps->pic_width_in_mbs_minus1+1)-1)) < 0)
+      return retCode;
+
+    if ((retCode = ue_v(bitbuf, &sps->frame_crop_right_offset, 8*(sps->pic_width_in_mbs_minus1+1)-sps->frame_crop_left_offset-1)) < 0)
+      return retCode;
+
+    if ((retCode = ue_v(bitbuf, &sps->frame_crop_top_offset, 8*(sps->pic_height_in_map_units_minus1+1)-1)) < 0)
+      return retCode;
+
+    if ((retCode = ue_v(bitbuf, &sps->frame_crop_bottom_offset, 8*(sps->pic_height_in_map_units_minus1+1)-sps->frame_crop_top_offset-1)) < 0)
+      return retCode;
+    
+    TInt cropUnitX = 2;
+    TInt cropUnitY = 2 * ( 2 - sps->frame_mbs_only_flag );
+    
+    TInt leftBorder = cropUnitX * sps->frame_crop_left_offset;
+    TInt rightBorder = aWidth - ( cropUnitX * sps->frame_crop_right_offset );
+    
+    aWidth = rightBorder - leftBorder;
+    
+    TInt topBorder = cropUnitY * sps->frame_crop_top_offset;
+    TInt bottomBorder = ( 16 * (sps->pic_height_in_map_units_minus1 + 1) ) -
+                        cropUnitY * sps->frame_crop_bottom_offset;
+                        
+    aHeight = bottomBorder - topBorder;
+    
+  }
+
+  if ((retCode = u_n(bitbuf, 1, &sps->vui_parameters_present_flag)) < 0)
+    return retCode;
+
+  setVUIdefaults(sps);
+
+  if (sps->vui_parameters_present_flag) {
+    if ((retCode = getVUI(bitbuf, &sps->vui_parameters)) < 0)
+      return retCode;
+  }
+
+  if (bibSkipTrailingBits(bitbuf) < 0)
+    return PS_ERROR;
+
+  return PS_OK;
+}
+
+/*
+ *
+ * psCloseParametersSets:
+ *
+ * Parameters:
+ *      spsList               The sequence parameter set list
+ *      ppsList               The picture parameter set list
+ *
+ * Fucntion:
+ *      Free all parameter sets
+ *
+ * Returns:
+ *      -
+ */
+void psCloseParametersSets(seq_parameter_set_s **spsList,
+                           pic_parameter_set_s **ppsList)
+{
+  int i;
+
+  for (i = 0; i < PS_MAX_NUM_OF_SPS; i++) {
+    psCloseSPS(spsList[i]);
+    spsList[i] = 0;
+  }
+
+  for (i = 0; i < PS_MAX_NUM_OF_PPS; i++) {
+    psClosePPS(ppsList[i]);
+    ppsList[i] = 0;
+  }
+}
+
+/*
+ *
+ * psClosePPS:
+ *
+ * Parameters:
+ *      pps                   the picture parameter set to be freed
+ *
+ * Function:
+ *      free the picture parameter set
+ *
+ * Returns:
+ *      -
+ */
+void psClosePPS( pic_parameter_set_s *pps )
+{
+  if (pps == 0)
+    return;
+  
+  	// [KW]: Added
+  	if (pps->codedPPSBuffer)
+	  	User::Free(pps->codedPPSBuffer);
+
+
+  if (pps->slice_group_id)
+    User::Free(pps->slice_group_id);
+//    nccFree(pps->slice_group_id);
+
+//  nccFree(pps);
+	User::Free(pps);
+}
+
+
+/*
+ *
+ * psCloseSPS:
+ *
+ * Parameters:
+ *      sps                   the sequence parameter set to be freed
+ *
+ * Fucntion:
+ *      free the sequence parameter set
+ *
+ * Returns:
+ *      -
+ */
+void psCloseSPS( seq_parameter_set_s *sps )
+{
+  if (sps == 0)
+    return;
+  	
+  	// [KW]: Added
+  	if (sps->codedSPSBuffer)
+	  	User::Free(sps->codedSPSBuffer);
+
+//  nccFree(sps);
+  User::Free(sps);
+}
+
+
+// psParseLevelFromSPS
+// Returns the baseline profile level from SPS
+TInt psParseLevelFromSPS( bitbuffer_s *bitbuf, TInt& aLevel )
+{
+  	TInt retCode;
+  	TUint profile_idc;                                      // u(8)
+  	Boolean constraint_set0_flag;                          // u(1)
+  	Boolean constraint_set1_flag;                          // u(1)
+  	Boolean constraint_set2_flag;                          // u(1)
+  	Boolean constraint_set3_flag;                          // u(1)
+  	Boolean reserved_zero_4bits;                           // u(4)
+  	TUint level_idc;                                        // u(8)      
+  
+  	// Parse sequence parameter set syntax until sps id
+  	if ((retCode = u_n(bitbuf, 8, &profile_idc)) < 0)
+    	return retCode;
+
+  	// If constraint_set0_flag == 1, stream is Baseline Profile compliant 
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set0_flag)) < 0)
+    	return retCode;
+
+  	// If constraint_set1_flag == 1, stream is Main Profile compliant 
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set1_flag)) < 0)
+    	return retCode;
+
+  	// If constraint_set2_flag == 1, stream is Extended Profile compliant 
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set2_flag)) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set3_flag)) < 0)
+    	return retCode;
+
+  	// If CABAC is not defined we support only baseline compliant streams 
+	if (profile_idc != PS_BASELINE_PROFILE_IDC && constraint_set0_flag == 0)
+   		return PS_ERR_UNSUPPORTED_PROFILE;
+
+  	// We don't care what is in these bits 
+  	if ((retCode = u_n(bitbuf, 4, &reserved_zero_4bits)) < 0)
+    	return retCode;
+
+  	// Fetch level 
+  	if ((retCode = u_n(bitbuf, 8, &level_idc)) < 0)
+    	return retCode;
+  
+  	aLevel = level_idc;
+  
+  	if ( level_idc == 11 && constraint_set3_flag == 1 )
+    	aLevel = 101;  // level 1b
+  
+  	return KErrNone;
+}
+
+
+// AddBytesToBuffer
+// Adds aNumBytes bytes to bit buffer aBitBuffer, reallocates the bit buffer data if necessary.
+TInt AddBytesToBuffer(bitbuffer_s *aBitBuffer, TUint aNumBytes)
+{
+	TInt i;
+	
+	// Reallocate the bitbuffer data
+	aBitBuffer->data = (TUint8 *) User::ReAlloc(aBitBuffer->data, (aBitBuffer->dataLen+aNumBytes));
+
+	if (aBitBuffer->data == 0)
+        return KErrNoMemory;
+
+	// Set the new bytes as zeros
+	for (i=aBitBuffer->dataLen; i<aBitBuffer->dataLen+aNumBytes; i++)
+	{
+		aBitBuffer->data[i] = 0;
+	}
+
+	return KErrNone;
+}
+
+
+#ifdef VIDEOEDITORENGINE_AVC_EDITING
+
+
+/*
+ *
+ * psGetAspectRatio:
+ *      
+ * Parameters:
+ *      sps                   Sequence parameter set
+ *      width                 Horizontal size of the sample aspect ratio
+ *      height                Vertical size of the sample aspect ratio
+ *
+ * Function:
+ *      Return sample aspect ratio in width and height
+ *
+ * Returns:
+ *      -
+ */
+void psGetAspectRatio(seq_parameter_set_s *sps, int *width, int *height)
+{
+  vui_parameters_s *vui;
+
+  vui = &sps->vui_parameters;
+
+  *width  = 0;
+  *height = 0;
+
+  if (sps->vui_parameters_present_flag &&
+      vui->aspect_ratio_info_present_flag &&
+      vui->aspect_ratio_idc != 0 &&
+      (vui->aspect_ratio_idc <= 13 || vui->aspect_ratio_idc == 255))
+  {
+    if (vui->aspect_ratio_idc == 255) {
+      /* Extended_SAR */
+      if (vui->sar_width != 0 && vui->sar_height != 0) {
+        *width  = vui->sar_width;
+        *height = vui->sar_height;
+      }
+    }
+    else {
+      *width  = aspectRatioArr[vui->aspect_ratio_idc-1].width;
+      *height = aspectRatioArr[vui->aspect_ratio_idc-1].height;
+    }
+  }
+
+}
+
+
+// CompareSPSSets
+// Compares two SPS input sets to see if we can use one for both clips, if exact match is not required
+// then some parameters maybe be different in the two sets. 
+TInt CompareSPSSets( seq_parameter_set_s *aSPSSet1, seq_parameter_set_s *aSPSSet2, TBool aExactMatch )
+{
+	TUint i;
+
+	// Different maxFrameNum & maxPOCLsb can be handled by modifying the slice header, thus do not return EFalse
+	if ( aExactMatch )
+	{
+		// If exact match is required, return false for different max frame number value
+		if ( aSPSSet1->log2_max_frame_num_minus4 != aSPSSet2->log2_max_frame_num_minus4 )
+			return EFalse;	
+	}
+	
+	if ( aSPSSet1->pic_order_cnt_type != aSPSSet2->pic_order_cnt_type )
+	{
+		return EFalse;
+	}
+	else
+	{
+	  	if (aSPSSet1->pic_order_cnt_type == 0) 
+  		{
+			// Different maxFrameNum & maxPOCLsb can be handled by modifying the slice header, thus do not return EFalse
+			if ( aExactMatch )
+			{
+				// If exact match is required, return false for different max POCLSB number value
+				if ( aSPSSet1->log2_max_pic_order_cnt_lsb_minus4 != aSPSSet2->log2_max_pic_order_cnt_lsb_minus4 )
+					return EFalse;	
+			}
+	
+  		}
+	  	else if (aSPSSet1->pic_order_cnt_type == 1) 
+  		{
+			if ( aSPSSet1->delta_pic_order_always_zero_flag != aSPSSet2->delta_pic_order_always_zero_flag ||
+				 aSPSSet1->offset_for_non_ref_pic != aSPSSet2->offset_for_non_ref_pic ||
+				 aSPSSet1->num_ref_frames_in_pic_order_cnt_cycle != aSPSSet2->num_ref_frames_in_pic_order_cnt_cycle )
+			{
+				return EFalse;
+			}
+
+	    	for (i = 0; i < aSPSSet1->num_ref_frames_in_pic_order_cnt_cycle; i++) 
+    		{
+				if ( aSPSSet1->offset_for_ref_frame[i] != aSPSSet2->offset_for_ref_frame[i] )
+				{
+					return EFalse;
+				}
+    		}
+  		}
+	}
+
+	if ( aSPSSet1->num_ref_frames != aSPSSet2->num_ref_frames )
+	{
+		return EFalse;
+	}
+	
+	// Direct 8x8 inference flag is not used in baseline, ignore
+
+	return ETrue;
+}
+
+
+// IsSPSSupported
+// Checks if the input SPS contains supported values. Returns KErrNotSupported if 
+// unsupported parameters are found.
+TInt IsSPSSupported( seq_parameter_set_s *aSPS )
+{
+
+	// Only Baseline profile supported at the moment
+	if ( aSPS->profile_idc != PS_BASELINE_PROFILE_IDC )
+	{
+		return KErrNotSupported;
+	}
+	
+	// Check if maximum supported level is exceeded
+	if ( aSPS->level_idc > PS_MAX_SUPPORTED_LEVEL )
+	{
+		return KErrNotSupported;
+	}
+	
+	// For now more than one reference frames are not supported
+	if ( aSPS->num_ref_frames > 1 )
+	{
+		return KErrNotSupported;
+	}
+	
+	// Coded fields are not supported
+	if ( !aSPS->frame_mbs_only_flag )
+	{
+		return KErrNotSupported;
+	}
+	
+	if ( aSPS->vui_parameters_present_flag )
+	{
+		if ( aSPS->vui_parameters.num_reorder_frames != 0 && aSPS->pic_order_cnt_type != 2)
+		{
+			// Since we can't be sure how many input frames we have to buffer before getting 
+			// an output picture, return KErrNotSupported
+			return KErrNotSupported;
+		}
+	}
+	else
+	{
+		if ( aSPS->pic_order_cnt_type != 2)
+		{
+			// Since we can't be sure how many input frames we have to buffer before getting 
+			// an output picture, return KErrNotSupported
+			return KErrNotSupported;
+		}
+	}
+	
+	return KErrNone;
+}
+
+
+// IsPPSSupported
+// Checks if the input PPS contains supported values. Returns KErrNotSupported if 
+// unsupported parameters are found.
+TInt IsPPSSupported( pic_parameter_set_s *aPPS )
+{
+
+	// For baseline, both prediction values shall be zero
+	if( aPPS->weighted_pred_flag != 0 || aPPS->weighted_bipred_idc != 0)
+	{
+		return KErrNotSupported;
+	}
+	
+	// For baseline, entropy coding mode shall be zero
+	if ( aPPS->entropy_coding_mode_flag != 0 )
+	{
+		return KErrNotSupported;
+	}
+	
+	if ( aPPS->num_slice_groups_minus1 > PS_BASELINE_MAX_SLICE_GROUPS )
+	{
+		return KErrNotSupported;
+	}
+
+	return KErrNone;
+}
+
+
+// psParseSPS
+// Parses the input SPS set. Modifies the SPS id if a conflicting id is found 
+// and stores the modified data to codedSPSBuffer for later use.
+TInt psParseSPS( bitbuffer_s *bitbuf, seq_parameter_set_s **spsList, TUint aFrameFromEncoder, TBool *aEncodeUntilIDR, TUint *aNumSPS )
+{
+  	seq_parameter_set_s *sps;
+  	TUint i;
+  	TInt retCode;
+  	TUint bitPosit = 0;
+  	TUint bytePosit = 0;
+  	TUint profile_idc;                                      // u(8)
+  	Boolean constraint_set0_flag;                          // u(1)
+  	Boolean constraint_set1_flag;                          // u(1)
+  	Boolean constraint_set2_flag;                          // u(1)
+  	Boolean constraint_set3_flag;                          // u(1)
+  	Boolean reserved_zero_4bits;                           // u(4)
+  	TUint level_idc;                                        // u(8)
+  	TUint seq_parameter_set_id;                             // ue(v)
+  	TUint newSPSId = 0;
+  	TUint possibleIdConflict = 0;
+  	TUint useOneSPS = 0;
+
+
+  	if (!aFrameFromEncoder)
+  	{	
+	  	// Reset the encode until IDR flag if this SPS is not from the encoder.
+  		*aEncodeUntilIDR = EFalse;
+  	}
+
+  	// Parse sequence parameter set syntax until sps id
+  	if ((retCode = u_n(bitbuf, 8, &profile_idc)) < 0)
+    	return retCode;
+	
+  	// If constraint_set0_flag == 1, stream is Baseline Profile compliant 
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set0_flag)) < 0)
+    	return retCode;
+
+  	// If constraint_set1_flag == 1, stream is Main Profile compliant 
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set1_flag)) < 0)
+    	return retCode;
+
+  	// If constraint_set2_flag == 1, stream is Extended Profile compliant 
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set2_flag)) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n(bitbuf, 1, &constraint_set3_flag)) < 0)
+    	return retCode;
+
+  	// If CABAC is not defined we support only baseline compliant streams 
+	if (profile_idc != PS_BASELINE_PROFILE_IDC && constraint_set0_flag == 0)
+   		return PS_ERR_UNSUPPORTED_PROFILE;
+
+  	// We don't care what is in these bits 
+  	if ((retCode = u_n(bitbuf, 4, &reserved_zero_4bits)) < 0)
+    	return retCode;
+
+  	// Fetch level 
+  	if ((retCode = u_n(bitbuf, 8, &level_idc)) < 0)
+    	return retCode;
+
+  	// Find level in the list of legal levels 
+  	for (i = 0; i < NUM_LEVELS; i++) 
+  	{
+    	if ((int)level_idc == levelArray[i].levelNumber)
+      		break;
+  	}
+
+  	// If level was not found in the list, return with error 
+  	if (i == NUM_LEVELS)
+    	return PS_ERR_ILLEGAL_VALUE;
+
+  	// Get sequence parameter set id 
+  	if ((retCode = ue_v(bitbuf, &seq_parameter_set_id, PS_MAX_NUM_OF_SPS-1)) < 0)
+    	return retCode;
+
+  	// Pointer to sequence parameter set structure 
+  	sps = spsList[seq_parameter_set_id];
+
+  	// Allocate memory for SPS, if it has not been allocated already 
+  	if (!sps) 
+  	{
+    	sps = (seq_parameter_set_s *) User::Alloc(sizeof(seq_parameter_set_s));
+    	
+    	if (sps == 0) 
+    	{
+			PRINT((_L("Error while allocating memory for SPS.\n")));
+      			return PS_ERR_MEM_ALLOC;
+    	}
+    	
+    	memset( sps, 0, sizeof(seq_parameter_set_s));
+    	spsList[seq_parameter_set_id] = sps;
+
+  		sps->seq_parameter_set_id = seq_parameter_set_id;
+  		(*aNumSPS)++;
+  	}
+  	else
+  	{
+  		// There might be a conflicting Id with an existing SPS set
+  		// Give the new SPS set the next free SPS Id
+  		possibleIdConflict = 1;
+  		newSPSId = 0;
+  		useOneSPS = 1;
+  		
+  		// Search for the first free SPS id
+  		while (spsList[newSPSId])
+  		{
+  			newSPSId++;
+  		}
+  	
+  		// And allocate memory for the SPS
+    	sps = (seq_parameter_set_s *) User::Alloc(sizeof(seq_parameter_set_s));
+    	
+    	if (sps == 0) 
+    	{
+      		PRINT((_L("Error while allocating memory for SPS.\n")));
+      			return PS_ERR_MEM_ALLOC;
+    	}
+    
+    	memset( sps, 0, sizeof(seq_parameter_set_s));
+    
+    	sps->seq_parameter_set_id = newSPSId;
+
+  		// Store the position of the bit buffer
+  		bitPosit = bitbuf->bitpos;
+  		bytePosit = bitbuf->bytePos;
+  	}
+
+
+  	// Copy temporary variables to sequence parameter set structure 
+  	sps->profile_idc          = profile_idc;
+  	sps->constraint_set0_flag = constraint_set0_flag;
+  	sps->constraint_set1_flag = constraint_set1_flag;
+  	sps->constraint_set2_flag = constraint_set2_flag;
+  	sps->constraint_set3_flag = constraint_set3_flag;
+  	sps->reserved_zero_4bits  = reserved_zero_4bits;
+  	sps->level_idc            = level_idc;
+
+	// Initialize
+	sps->maxFrameNumChanged = 0;
+	sps->maxPOCNumChanged = 0;
+	
+  	// This defines how many bits there are in frame_num syntax element 
+  	if ((retCode = ue_v(bitbuf, &sps->log2_max_frame_num_minus4, 12)) < 0)
+    	return retCode;
+
+  	// Fetch POC type 
+  	if ((retCode = ue_v(bitbuf, &sps->pic_order_cnt_type, 2)) < 0)
+    	return retCode;
+
+  	if (sps->pic_order_cnt_type == 0) 
+  	{
+    	if ((retCode = ue_v(bitbuf, &sps->log2_max_pic_order_cnt_lsb_minus4, 12)) < 0)
+      		return retCode;
+  	}
+  	else if (sps->pic_order_cnt_type == 1) 
+  	{
+    	if ((retCode = u_n(bitbuf, 1, &sps->delta_pic_order_always_zero_flag)) < 0)
+      		return retCode;
+
+    	if ((retCode = se_v_long(bitbuf, &sps->offset_for_non_ref_pic)) < 0)
+      		return retCode;
+
+    	if ((retCode = se_v_long(bitbuf, &sps->offset_for_top_to_bottom_field)) < 0)
+      		return retCode;
+
+    	if ((retCode = ue_v(bitbuf, &sps->num_ref_frames_in_pic_order_cnt_cycle, 255)) < 0)
+      		return retCode;
+
+    	for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) 
+    	{
+      		if ((retCode = se_v_long(bitbuf, &sps->offset_for_ref_frame[i])) < 0)
+        		return retCode;
+    	}
+  	}
+
+  	if ((retCode = ue_v(bitbuf, &sps->num_ref_frames, 16)) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n(bitbuf, 1, &sps->gaps_in_frame_num_value_allowed_flag)) < 0)
+    	return retCode;
+
+  	if ((retCode = ue_v(bitbuf, &sps->pic_width_in_mbs_minus1, MAX_PIC_WIDTH_IN_MBS-1)) < 0)
+    	return retCode;
+
+  	if ((retCode = ue_v(bitbuf, &sps->pic_height_in_map_units_minus1, MAX_PIC_WIDTH_IN_MBS-1)) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n(bitbuf, 1, &sps->frame_mbs_only_flag)) < 0)
+    	return retCode;
+
+  	if (!sps->frame_mbs_only_flag) 
+  	{
+    	return PS_ERR_UNSUPPORTED_FEATURE;
+  	}
+
+  	if ((retCode = u_n(bitbuf, 1, &sps->direct_8x8_inference_flag)) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n(bitbuf, 1, &sps->frame_cropping_flag)) < 0)
+    	return retCode;
+
+  	// Fetch cropping window 
+  	if (sps->frame_cropping_flag) 
+  	{
+    	if ((retCode = ue_v(bitbuf, &sps->frame_crop_left_offset, 8*(sps->pic_width_in_mbs_minus1+1)-1)) < 0)
+      		return retCode;
+
+    	if ((retCode = ue_v(bitbuf, &sps->frame_crop_right_offset, 8*(sps->pic_width_in_mbs_minus1+1)-sps->frame_crop_left_offset-1)) < 0)
+      		return retCode;
+
+    	if ((retCode = ue_v(bitbuf, &sps->frame_crop_top_offset, 8*(sps->pic_height_in_map_units_minus1+1)-1)) < 0)
+      		return retCode;
+
+    	if ((retCode = ue_v(bitbuf, &sps->frame_crop_bottom_offset, 8*(sps->pic_height_in_map_units_minus1+1)-sps->frame_crop_top_offset-1)) < 0)
+      		return retCode;
+  	}
+
+  	if ((retCode = u_n(bitbuf, 1, &sps->vui_parameters_present_flag)) < 0)
+    	return retCode;
+
+  	setVUIdefaults(sps);
+
+  	if (sps->vui_parameters_present_flag) 
+  	{
+    	if ((retCode = getVUI(bitbuf, &sps->vui_parameters)) < 0)
+      		return retCode;
+  	}
+
+  	if (bibSkipTrailingBits(bitbuf) < 0)
+    	return PS_ERROR;
+  
+  	// Store the size of the SPS set
+  	sps->SPSlength = bitbuf->bytePos;
+  
+	syncBitBufferBitpos(bitbuf);
+	
+  	// If we had a possible conflict, compare the SPS sets with the same id to see if only one SPS set can be used.
+  	if (possibleIdConflict)
+  	{
+  		// Check if one SPS can be used instead of two separate ones
+	  	useOneSPS = CompareSPSSets(spsList[seq_parameter_set_id],sps,EFalse);
+	  	
+	  	if (!useOneSPS)
+	  	{
+  			TUint trailingBits = GetNumTrailingBits(bitbuf);
+  			TInt diff = 0;
+			TUint oldSPSId = seq_parameter_set_id;
+			TUint oldIdLength = ReturnUnsignedExpGolombCodeLength(oldSPSId);
+			TUint newIdLength = ReturnUnsignedExpGolombCodeLength(newSPSId);
+			TUint storeSPS = 1;
+		
+  			for (i=0; i<PS_MAX_NUM_OF_SPS; i++)
+  			{
+			  	// Check if an older SPS matches exactly this one, then use the old
+  				if (spsList[i])
+	  				useOneSPS = CompareSPSSets(spsList[i],sps,ETrue);
+  			
+	  			if (useOneSPS)
+	  			{
+	  				newSPSId = i;
+	  				storeSPS  =0;
+  					break;		
+	  			}
+  			}
+  		
+	  		if ( newSPSId > PS_MAX_NUM_OF_SPS )
+	  		{
+	  			// We have reached maximum number of SPS, return an error
+	  			return PS_ERROR;
+	  		}
+	  		
+	  		(*aNumSPS)++;
+	  	
+	  		// Set indexChanged to true and give the new index to old SPS, so that (new) PPS can refer to the new SPS
+	  		spsList[seq_parameter_set_id]->indexChanged = 1;
+	  		spsList[seq_parameter_set_id]->newSPSId = newSPSId;	// The new Id
+	  	
+	  		if (aFrameFromEncoder)
+	  		{
+		  		spsList[seq_parameter_set_id]->encSPSId = newSPSId;	// The new Id
+		  	
+		  		// Store information that there are different SPS in use, we have to encode until an IDR NAL unit.
+		  		*aEncodeUntilIDR = ETrue;
+	  		}
+			else
+		  		spsList[seq_parameter_set_id]->origSPSId = newSPSId;	// The new Id
+		  	
+	  		
+	  		// Store the new SPS at the new index and modify SPS id, 
+	  		// unless we are using a previously stored SPS
+	  		if(storeSPS)
+	  		{
+		  		spsList[newSPSId] = sps;
+		  		
+				// Restore the bit buffer position at the SPS Id
+				bitbuf->bitpos = bitPosit;
+				bitbuf->bytePos = bytePosit;
+		
+				if(trailingBits > 8)
+				{
+					trailingBits = 8;
+				}
+		
+				if ( oldIdLength == newIdLength )
+				{
+					// Just encode the new Id on top of the old Id
+					bitbuf->bitpos += oldIdLength;
+					if (bitbuf->bitpos > 8)
+					{	
+						// Go to the right byte and bit position
+						bitbuf->bytePos -= bitbuf->bitpos / 8;
+						bitbuf->bitpos = bitbuf->bitpos % 8;
+					}
+				
+					EncodeUnsignedExpGolombCode(bitbuf, newSPSId);
+				}
+				else if ( oldIdLength < newIdLength )
+				{
+					diff = newIdLength - oldIdLength;
+			
+					// Adjust the SPS length
+					if (diff >= 8)
+					{
+						// Add as many extra bytes as is required
+						sps->SPSlength += (diff / 8);
+					}
+				
+					if ( trailingBits < (diff % 8) )
+					{
+						// Add one byte since there aren't enough trailing bits for the extra bits
+						sps->SPSlength += 1;
+					}
+			
+					ShiftBufferRight(bitbuf, diff, trailingBits, oldIdLength);
+	
+					// After shifting, encode the new value to the bit buffer
+					EncodeUnsignedExpGolombCode(bitbuf, newSPSId);
+				}
+				else
+				{
+					// New id's length is smaller than old id's length
+					diff = oldIdLength - newIdLength;
+			
+					if (diff >= 8)
+					{
+						// Adjust the SPS length
+						sps->SPSlength -= (diff / 8);
+					}
+			
+					ShiftBufferLeft(bitbuf, diff, oldIdLength);
+			
+					// After shifting, encode the new value to the bit buffer
+					EncodeUnsignedExpGolombCode(bitbuf, newSPSId);
+				}
+	  		}
+	  	}
+	  	else	// Use one SPS for both
+	  	{
+	  		// Reset indexChanged to false 
+	  		spsList[seq_parameter_set_id]->indexChanged = 0;
+	  		
+	  		// Check if the frame numbering or POC numbering has to be changed
+	  		if (spsList[seq_parameter_set_id]->log2_max_frame_num_minus4 != sps->log2_max_frame_num_minus4)
+	  		{
+	  			spsList[seq_parameter_set_id]->maxFrameNumChanged = 1;
+	  		
+	  			if (aFrameFromEncoder)
+			  		spsList[seq_parameter_set_id]->encMaxFrameNum = sps->log2_max_frame_num_minus4;
+				else
+		  			spsList[seq_parameter_set_id]->origMaxFrameNum = sps->log2_max_frame_num_minus4;
+	  		}
+	  		else
+	  		{
+	  			// Reset the value in case it was changed for another clip earlier
+	  			spsList[seq_parameter_set_id]->maxFrameNumChanged = 0;
+	  		}
+
+	  		if (spsList[seq_parameter_set_id]->log2_max_pic_order_cnt_lsb_minus4 != sps->log2_max_pic_order_cnt_lsb_minus4)
+	  		{
+	  			spsList[seq_parameter_set_id]->maxPOCNumChanged = 1;
+	  		
+	  			if (aFrameFromEncoder)
+			  		spsList[seq_parameter_set_id]->encMaxPOCNum = sps->log2_max_pic_order_cnt_lsb_minus4;
+				else
+		  			spsList[seq_parameter_set_id]->origMaxPOCNum = sps->log2_max_pic_order_cnt_lsb_minus4;
+	  		}
+	  		else
+	  		{
+	  			// Reset the value in case it was changed for another clip earlier
+	  			spsList[seq_parameter_set_id]->maxPOCNumChanged = 0;
+	  		}
+	  	}
+  	}
+
+  	if ( IsSPSSupported(sps) == KErrNotSupported )
+  		return KErrNotSupported;
+  	
+
+  	// Store the buffer containing the SPS set in order to later pass it to the 3gpmp4library
+  	// If we use the same sps for both, don't allocate, otherwise allocate
+  	if ( !useOneSPS )
+  	{
+  		
+		// Store the buffer containing the SPS set in order to later pass it to the 3gpmp4library
+  		sps->codedSPSBuffer = (TUint8*) User::Alloc(sps->SPSlength);    
+
+		if (sps->codedSPSBuffer == 0)
+			return PS_ERR_MEM_ALLOC;
+  
+  		for (i=0; i<sps->SPSlength; i++)
+  		{
+  			sps->codedSPSBuffer[i] = bitbuf->data[i];
+  		}
+  	}
+  	else if (possibleIdConflict)
+  	{
+  		// Free the SPS since we will use only one which has been already allocated earlier
+	  	User::Free(sps);
+  	}
+
+
+  	return PS_OK;
+}
+
+
+// ComparePPSSets
+// Compares two input PPS sets to see if a single PPS set could be used for both. 
+// Returns ETrue if the sets are similar enough, EFalse otherwise.
+TInt ComparePPSSets( pic_parameter_set_s *aPPSSet1, pic_parameter_set_s *aPPSSet2 )
+{
+	TUint i;
+
+	// This is the most likely parameter to differ, thus check it first
+	if ( aPPSSet1->pic_init_qp_minus26 != aPPSSet2->pic_init_qp_minus26 ||
+		 aPPSSet1->pic_init_qs_minus26 != aPPSSet2->pic_init_qs_minus26 )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->entropy_coding_mode_flag != aPPSSet2->entropy_coding_mode_flag )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->pic_order_present_flag != aPPSSet2->pic_order_present_flag )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->num_slice_groups_minus1 != aPPSSet2->num_slice_groups_minus1 )
+	{
+		return EFalse;
+	}
+	else
+	{
+	  	if ( aPPSSet1->num_slice_groups_minus1 > 0 ) 
+  		{
+			if ( aPPSSet1->slice_group_map_type != aPPSSet2->slice_group_map_type ) 
+			{
+				return EFalse;
+			}
+			
+	    	switch ( aPPSSet1->slice_group_map_type ) 
+   	 		{
+
+	      		case PS_SLICE_GROUP_MAP_TYPE_INTERLEAVED:
+    	    		for (i = 0; i <= aPPSSet1->num_slice_groups_minus1; i++) 
+        			{
+						if ( aPPSSet1->run_length_minus1[i] != aPPSSet2->run_length_minus1[i] ) 
+						{
+							return EFalse;
+						}
+	        		}
+    	    		break;
+
+      			case PS_SLICE_GROUP_MAP_TYPE_DISPERSED:
+        			break;
+
+	      		case PS_SLICE_GROUP_MAP_TYPE_FOREGROUND:
+    	    		for (i = 0; i < aPPSSet1->num_slice_groups_minus1; i++) 
+        			{
+						if ( aPPSSet1->top_left[i] != aPPSSet2->top_left[i] ||
+						     aPPSSet1->bottom_right[i] != aPPSSet2->bottom_right[i] ) 
+						{
+							return EFalse;
+						}
+	        		}
+    	    		break;
+
+	      		case PS_SLICE_GROUP_MAP_TYPE_CHANGING_3:
+    	  		case PS_SLICE_GROUP_MAP_TYPE_CHANGING_4:
+      			case PS_SLICE_GROUP_MAP_TYPE_CHANGING_5:
+					if ( aPPSSet1->slice_group_change_direction_flag != aPPSSet2->slice_group_change_direction_flag ||
+					     aPPSSet1->slice_group_change_rate_minus1 != aPPSSet2->slice_group_change_rate_minus1 ) 
+					{
+						return EFalse;
+					}
+        			break;
+
+	      		case PS_SLICE_GROUP_MAP_TYPE_EXPLICIT:
+					if ( aPPSSet1->pic_size_in_map_units_minus1 != aPPSSet2->pic_size_in_map_units_minus1 ) 
+					{
+						return EFalse;
+					}
+
+	        		for( i = 0; i <= aPPSSet1->pic_size_in_map_units_minus1; i++ ) 
+    	    		{
+						if ( aPPSSet1->slice_group_id[i] != aPPSSet2->slice_group_id[i] ) 
+						{
+							return EFalse;
+						}
+        			}
+
+	        		break;
+
+    	  		default:
+        			// Cannnot happen 
+        			break;
+  			}
+  		}
+	}
+
+	if ( aPPSSet1->num_ref_idx_l0_active_minus1 != aPPSSet2->num_ref_idx_l0_active_minus1 ||
+		 aPPSSet1->num_ref_idx_l1_active_minus1 != aPPSSet2->num_ref_idx_l1_active_minus1 )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->weighted_pred_flag != aPPSSet2->weighted_pred_flag ||
+		 aPPSSet1->weighted_bipred_idc != aPPSSet2->weighted_bipred_idc )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->chroma_qp_index_offset != aPPSSet2->chroma_qp_index_offset )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->deblocking_filter_parameters_present_flag != aPPSSet2->deblocking_filter_parameters_present_flag )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->constrained_intra_pred_flag != aPPSSet2->constrained_intra_pred_flag )
+	{
+		return EFalse;
+	}
+
+	if ( aPPSSet1->redundant_pic_cnt_present_flag != aPPSSet2->redundant_pic_cnt_present_flag )
+	{
+		return EFalse;
+	}
+
+	return ETrue;
+}
+
+
+// GetNumTrailingBits
+// Returns the number of trailing (zero) bits in the input bit buffer.
+TInt GetNumTrailingBits(bitbuffer_s *aBitBuffer)
+{
+	TInt i;
+	TUint bit = 0;
+
+	for (i=0; i<8; i++)
+	{
+		// Get the i'th bit from the end
+		bit = (aBitBuffer->data[aBitBuffer->dataLen - 1] & (1 << i)) >> i;
+		if (bit)
+		{
+			return (i);		// Return the number of trailing bits here
+		}
+	}
+	
+	// Return 9 for cases when there are one or more zero byte at the end
+	return (9);
+}
+
+
+// ReturnUnsignedExpGolombCodeLength
+// Returns the amount of bits required for encoding the input aValue with unsigned Exp-Golomb codes.
+TInt ReturnUnsignedExpGolombCodeLength(TUint aValue)
+{
+	TUint codeNumLength;
+	
+	codeNumLength = 0;
+	
+	aValue++;
+	
+	while ( aValue > 1 )
+	{
+		aValue >>= 1;
+		codeNumLength++;
+	}
+
+	// The required code length is codeNumLength*2+1
+	return ((codeNumLength << 1) + 1);
+}
+
+
+// EncodeUnsignedExpGolombCode
+// Encodes the input aValue to the bit buffer with unsigned Exp-Golomb codes.
+void EncodeUnsignedExpGolombCode(bitbuffer_s *aBitBuffer, TUint aValue)
+{
+	TUint codeLength;
+	TUint tempValue = aValue;
+	TInt i;
+	TUint8 byteValue;
+	 
+	// First, compute the required code length
+	codeLength = ReturnUnsignedExpGolombCodeLength(aValue);
+
+	// The Exp-Golomb coded value is the same as value+1 with the prefix zero bits,
+	// thus it can be simply coded by coding value+1 with the number of bits computed 
+	// by the above function.
+	aValue++;	
+
+	// Then write the bits to the bit buffer one bit at a time
+	for (i=codeLength-1; i>=0; i--)
+	{
+		tempValue = (aValue & (1 << i)) >> i;
+		
+		// Zero out the bitpos bit
+		byteValue = aBitBuffer->data[aBitBuffer->bytePos-1] & ~(1<<(aBitBuffer->bitpos-1));
+
+		// Add the bit from the value to be coded and store the result back to bit buffer
+		byteValue |= tempValue << (aBitBuffer->bitpos-1);
+		aBitBuffer->data[aBitBuffer->bytePos-1] = byteValue;
+		aBitBuffer->bitpos--;
+		
+		if(aBitBuffer->bitpos == 0)
+		{
+			aBitBuffer->bytePos++;
+			aBitBuffer->bitpos = 8;
+		}
+	}
+
+ 	// Update the currentBits value 
+ 	aBitBuffer->currentBits = aBitBuffer->data[aBitBuffer->bytePos-1];
+}
+
+
+// ShiftBitBufferBitsRight
+// This function shifts bits right by aDiff in the aBitBuffer, note that if 
+// the shift is more than 8 bits, full bytes should be shifted before calling this function.
+// The gap between unmodified and shofted part of the buffer is filled with zero bits
+void ShiftBitBufferBitsRight(bitbuffer_s *aBitBuffer, TInt aDiff)
+{
+	TUint8 byteValue;
+	TUint8 tempValue;
+	TUint8 bitMask;
+	TInt i;
+	
+ 	// Start from the end, shift bits in each byte until the current byte
+ 	for (i=aBitBuffer->dataLen-1; i>=aBitBuffer->bytePos; i--)
+ 	{
+		bitMask = (1 << aDiff) - 1;	// The aDiff lowest bits
+		
+		// Shift the bits in this byte right by aDiff
+ 		byteValue = aBitBuffer->data[i];
+ 		byteValue >>= aDiff;
+ 		
+ 		// The aDiff lowest bits from the next byte (to the left)
+ 		tempValue = aBitBuffer->data[i-1] & bitMask;
+ 		
+ 		tempValue <<= (8 - aDiff);
+ 		aBitBuffer->data[i] = byteValue | tempValue;
+ 	}
+ 	
+ 	// Take care of the first byte separately
+	bitMask = (1 << aBitBuffer->bitpos) - 1;	// The bitPos lowest bits
+	byteValue = aBitBuffer->data[aBitBuffer->bytePos-1] & bitMask;
+	byteValue >>= aDiff;		// Shift right by aDiff bits
+		
+	bitMask = 255 << (aBitBuffer->bitpos);	// Mask the 8-bitPos upper bits
+		
+	// Write the shifted value back to bit buffer
+	aBitBuffer->data[aBitBuffer->bytePos-1] = (bitMask & aBitBuffer->data[aBitBuffer->bytePos-1]) | byteValue;
+ 	
+ 	// Update the currentBits value 
+ 	aBitBuffer->currentBits = aBitBuffer->data[aBitBuffer->bytePos-1];
+}
+
+
+// ShiftBitBufferBitsLeft
+// This function shifts bits left by aDiff in the aBitBuffer, note that if 
+// the shift is more than 8 bits, full bytes should be shifted before calling this function.
+void ShiftBitBufferBitsLeft(bitbuffer_s *aBitBuffer, TInt aDiff)
+{
+	TUint8 byteValue;
+	TUint8 tempValue;
+	TUint8 bitMask;
+	TInt i;
+	
+	
+ 	// Take care of the first byte separately
+ 	if ( aBitBuffer->bitpos > aDiff )
+ 	{
+		bitMask = (1 << aBitBuffer->bitpos) - 1;	// The aBitBuf->bitpos lowest bits
+		byteValue = aBitBuffer->currentBits & bitMask;
+		
+		// Shift the byteValue left by aDiff
+		byteValue <<= aDiff;
+		// Take only the bitpos lowest bits from this value
+		byteValue &= bitMask;
+		
+		bitMask = 255 << (aBitBuffer->bitpos);	// Mask the 8-bitPos upper bits, i.e. the bits to the left from the start of the shift
+		byteValue = byteValue | (aBitBuffer->currentBits & bitMask);
+		aBitBuffer->data[aBitBuffer->bytePos-1] = byteValue;
+		
+		bitMask = 255 << (8 - aDiff);	// Mask the aDiff upper bits
+		byteValue = aBitBuffer->data[aBitBuffer->bytePos] & bitMask;
+		byteValue >>= (8 - aDiff);
+		
+		// "Add" the aDiff bits from the next byte (msb) to this byte (lsb)
+ 		aBitBuffer->data[aBitBuffer->bytePos-1] |= byteValue;
+ 	}
+ 	else
+ 	{
+		bitMask = 255 << (aBitBuffer->bitpos);	// Mask the 8-bitPos upper bits, i.e. the bits to the left from the start of the shift
+		aBitBuffer->data[aBitBuffer->bytePos-1] = aBitBuffer->currentBits & bitMask;
+		
+		bitMask = (1 << (8-aDiff+aBitBuffer->bitpos)) - 1;	// The 8-diff+aBitBuf->bitpos lowest bits
+		tempValue = aBitBuffer->data[aBitBuffer->bytePos] & bitMask;
+		
+		// Shift tempValue right by 8 - diff bits, resulting in bitpos lowest bits 
+		tempValue >>= (8 - aDiff);
+
+ 		aBitBuffer->data[aBitBuffer->bytePos-1] |= tempValue;
+ 	}
+ 	
+ 	
+ 	// Start from the current byte, shift bits in each byte until the end
+ 	for (i=aBitBuffer->bytePos; i<(aBitBuffer->dataLen-1); i++)
+ 	{
+ 	
+		bitMask = 255 << (8 - aDiff);	// Mask the 8-aDiff upper bits
+		byteValue = aBitBuffer->data[i+1] & bitMask;
+		byteValue >>= (8 - aDiff);
+		
+ 		tempValue = aBitBuffer->data[i];
+ 		tempValue <<= aDiff;
+
+ 		aBitBuffer->data[i] = byteValue | tempValue;
+ 	}
+ 	
+ 	// Take care of the last byte separately, just shift to the left
+	aBitBuffer->data[aBitBuffer->dataLen-1] <<= aDiff;
+ 	
+ 	// Update the currentBits value 
+ 	aBitBuffer->currentBits = aBitBuffer->data[aBitBuffer->bytePos-1];
+}
+
+
+// ShiftBufferLeftByOneByte
+// Shifts the bytes left in the bit buffer by one position starting from the current byte position.
+void ShiftBufferLeftByOneByte(bitbuffer_s *aBitBuffer)
+{
+	TInt i;
+	TUint8 byteValue;
+	TUint8 bitMask;
+
+	
+	// For the current byte, take 8-bitpos upper bits from this byte and bitpos lowest bits from the next 
+	// byte (this is ok since we are shift at least 8 bits when this function is called)
+	bitMask = 255 << (aBitBuffer->bitpos);	// Mask the 8-bitPos upper bits
+	aBitBuffer->data[aBitBuffer->bytePos] &= bitMask;
+
+	bitMask = (1 << aBitBuffer->bitpos) - 1;	// The aBitBuf->bitpos lowest bits
+	byteValue = aBitBuffer->data[aBitBuffer->bytePos+1] & bitMask;
+	aBitBuffer->data[aBitBuffer->bytePos] |= byteValue;
+	
+	// Start from the next byte position, and go through the whole buffer
+ 	for (i=aBitBuffer->bytePos+1; i<(aBitBuffer->dataLen-1); i++)
+ 	{
+ 		// Copy the next byte to here
+		aBitBuffer->data[i] =  	aBitBuffer->data[i+1];
+ 	}
+ 	
+ 	// Adjust the bit buffer length
+ 	aBitBuffer->dataLen--;
+}
+
+
+// ShiftBufferRightByOneByte
+// Shifts the bytes right in the bit buffer by one position starting from the current byte position.
+void ShiftBufferRightByOneByte(bitbuffer_s *aBitBuffer)
+{
+	TInt i;
+	
+	// Start from the last byte position, and go through the whole buffer until the current byte position
+	// Note: also the current byte can be shifted, since the bits that should not be shifted from that byte
+	// will be written over by the new value coded later, thus no error will be there.
+ 	for (i=aBitBuffer->dataLen-1; i>=aBitBuffer->bytePos; i--)
+ 	{
+ 		// Copy the next byte to here
+		aBitBuffer->data[i] =  	aBitBuffer->data[i-1];
+	}
+}
+
+
+// ShiftBufferRight
+// Shifts bits right in the input bit buffer by aDiff value, the bit buffer length is modified if required.
+void ShiftBufferRight(bitbuffer_s *aBitBuffer, TInt aDiff, TUint aTrailingBits, TUint aOldIdLength)
+{
+	TInt i;
+	
+	if ( aDiff >= 8 )
+	{
+		TUint bytesToShift = aDiff / 8;
+				
+		// Add byte(s) to the bit buffer
+		aBitBuffer->dataLen += bytesToShift;
+				
+		// Shift full bytes to right
+		for (i=0; i<bytesToShift; i++)
+		{
+			ShiftBufferRightByOneByte(aBitBuffer);
+			aDiff -= 8;
+		}
+				
+		aDiff = aDiff % 8;
+	}
+	
+	// If there are less trailing bits than we need to shift then we have to add one byte to the buffer		
+	if ( aTrailingBits < aDiff )	
+	{
+		// Have to add byte to the SPS set
+		aBitBuffer->dataLen += 1;
+	}
+
+	if (aDiff != 0)
+	{
+		// Shift the bits in the bit buffer to the right
+		ShiftBitBufferBitsRight(aBitBuffer, aDiff);
+	}
+				
+	// Adjust the bitbuffer bitpos value
+	aBitBuffer->bitpos += aOldIdLength;
+	if ( aBitBuffer->bitpos > 8 )
+	{
+		aBitBuffer->bitpos -= 8;
+		aBitBuffer->bytePos--;
+	}
+}
+
+
+// ShiftBufferLeft
+// Shifts bits left in the input bit buffer by aDiff value.
+void ShiftBufferLeft(bitbuffer_s *aBitBuffer, TInt aDiff, TUint aOldIdLength)
+{
+	TInt i;
+	
+	if (aDiff >= 8)
+	{
+		// Shift full bytes to the left before shifting bits
+		TUint bytesToShift = aDiff / 8;
+
+		// First, adjust the byte position to be correct
+		aBitBuffer->bytePos -= bytesToShift;
+				
+		for (i=0; i<bytesToShift; i++)
+		{
+			ShiftBufferLeftByOneByte(aBitBuffer);
+			aDiff -= 8;
+		}
+	}
+			
+	// Adjust the bit position of the bit buffer
+	aBitBuffer->bitpos += aOldIdLength;
+	if ( aBitBuffer->bitpos > 8 )
+	{
+		aBitBuffer->bitpos -= 8;
+		aBitBuffer->bytePos--;
+					
+		aBitBuffer->currentBits = aBitBuffer->data[aBitBuffer->bytePos-1];
+	}
+			
+	if ( aDiff != 0 )
+	{
+		// Shift the bits in the bit buffer to the left
+		ShiftBitBufferBitsLeft(aBitBuffer, aDiff);
+	}
+	
+}
+
+
+// psParsePPS
+// Parses the input PPS set, the PPS and SPS id's are modified if necessary 
+// and the modified data is stored in codedPPSBuffer.
+TInt psParsePPS( bitbuffer_s *bitbuf, pic_parameter_set_s **ppsList, seq_parameter_set_s **spsList, 
+				 TUint aFrameFromEncoder, TUint *aNumPPS )
+{
+  	pic_parameter_set_s *pps;
+  	TUint i, tmp;
+  	TInt len;
+  	TUint pic_parameter_set_id;
+  	TInt retCode;
+  	TUint pic_size_in_map_units_minus1;
+  	TUint newPPSId = 0;
+  	TUint possibleIdConflict = 0;
+  	TUint modifySPSId = 0;
+  	TUint bitPosit = 0;
+  	TUint bytePosit = 0;
+  	TInt bitSPSPosit = 0;
+  	TUint byteSPSPosit = 0;
+  	TUint useOnePPS = 0;
+
+  	// Parse pps id 
+  	if ((retCode = ue_v(bitbuf, &pic_parameter_set_id, PS_MAX_NUM_OF_PPS-1)) < 0)
+    	return retCode;
+
+  	// Allocate memory for pps if not already allocated
+  	pps = ppsList[pic_parameter_set_id];
+
+  	if (!pps) 
+  	{
+    	pps = (pic_parameter_set_s *) User::Alloc(sizeof(pic_parameter_set_s));
+    	
+    	if (pps == 0) 
+    	{
+      		PRINT((_L("Error while allocating memory for PPS.\n")));
+      		return PS_ERR_MEM_ALLOC;
+    	}
+    
+    	memset( pps, 0, sizeof(pic_parameter_set_s));
+    	ppsList[pic_parameter_set_id] = pps;
+    	
+    	(*aNumPPS)++;
+  	}
+  	else
+  	{
+  		// There might be a conflicting Id with an existing PPS set
+  		// Give the new SPS set the next free PPS Id
+  		possibleIdConflict = 1;
+  		useOnePPS = 1;
+  		newPPSId = 0;
+  	
+  		while (ppsList[newPPSId])
+  		{
+  			newPPSId++;
+  		}
+  	
+  		// Allocate memory for the PPS
+    	pps = (pic_parameter_set_s *) User::Alloc(sizeof(pic_parameter_set_s));
+    	
+    	if (pps == 0) 
+    	{
+      		PRINT((_L("Error while allocating memory for PPS.\n")));
+      		return PS_ERR_MEM_ALLOC;
+    	}
+    
+    	memset( pps, 0, sizeof(pic_parameter_set_s));
+    	pps->pic_parameter_set_id = newPPSId;
+    
+  		// Store the position of the bit buffer
+  		bitPosit = bitbuf->bitpos;
+  		bytePosit = bitbuf->bytePos;
+  	}
+
+
+  	// Parse the rest of the picture parameter set syntax
+  	if ((retCode = ue_v( bitbuf, &pps->seq_parameter_set_id, PS_MAX_NUM_OF_SPS-1)) < 0)
+    	return retCode;
+  
+  	// Check if the Id of the SPS that this PPS refers to has changed (and that 
+  	// the frame originated form the encoder)
+  	if( spsList[pps->seq_parameter_set_id]->indexChanged)
+  	{
+  		if ( !aFrameFromEncoder )
+  		{
+  			if (pps->seq_parameter_set_id != spsList[pps->seq_parameter_set_id]->origSPSId)
+  			{
+		  		// Indicate a changed SPS Id, perform the change at the end (when we know the size of the PPS set)
+  				modifySPSId = ETrue;
+  	
+  				// Store the position of the bit buffer
+  				bitSPSPosit = bitbuf->bitpos;
+  				byteSPSPosit = bitbuf->bytePos;
+  			}
+  		}
+  		else
+  		{
+	  		// Indicate a changed SPS Id, perform the change at the end (when we know the size of the PPS set)
+  			modifySPSId = ETrue;
+	  	
+  			// Store the position of the bit buffer
+  			bitSPSPosit = bitbuf->bitpos;
+  			byteSPSPosit = bitbuf->bytePos;
+  		}
+  	}
+
+  	// Fetch entropy coding mode. Mode is 0 for CAVLC and 1 for CABAC 
+  	if ((retCode = u_n( bitbuf, 1, &pps->entropy_coding_mode_flag)) < 0)
+    	return retCode;
+
+  	// If this flag is 1, POC related syntax elements are present in slice header 
+  	if ((retCode = u_n( bitbuf, 1, &pps->pic_order_present_flag)) < 0)
+    	return retCode;
+
+  	// Fetch the number of slice groups minus 1 
+  	if ((retCode = ue_v( bitbuf, &pps->num_slice_groups_minus1, PS_MAX_NUM_SLICE_GROUPS-1)) < 0)
+    	return retCode;
+
+  	if(pps->num_slice_groups_minus1 > 0 ) 
+  	{
+
+    	if ((retCode = ue_v( bitbuf, &pps->slice_group_map_type, 6)) < 0)
+      		return retCode;
+
+    	switch (pps->slice_group_map_type) 
+    	{
+
+      		case PS_SLICE_GROUP_MAP_TYPE_INTERLEAVED:
+        		for (i = 0; i <= pps->num_slice_groups_minus1; i++) 
+        		{
+          			if ((retCode = ue_v( bitbuf, &pps->run_length_minus1[i], MAX_PIC_SIZE_IN_MBS-1 )) < 0)
+            			return retCode;
+        		}
+        		break;
+
+      		case PS_SLICE_GROUP_MAP_TYPE_DISPERSED:
+        		break;
+
+      		case PS_SLICE_GROUP_MAP_TYPE_FOREGROUND:
+        		for (i = 0; i < pps->num_slice_groups_minus1; i++) 
+        		{
+          			// Fetch MB address of the top-left corner 
+          			if ((retCode = ue_v( bitbuf, &pps->top_left[i], MAX_PIC_SIZE_IN_MBS-1)) < 0)
+            			return retCode;
+          			// Fetch MB address of the bottom-right corner (top-left address must 
+          			// be smaller than or equal to bottom-right address)                  
+          			if ((retCode = ue_v( bitbuf, &pps->bottom_right[i], MAX_PIC_SIZE_IN_MBS-1)) < 0)
+            			return retCode;
+
+          			if (pps->top_left[i] > pps->bottom_right[i])
+            			return PS_ERR_ILLEGAL_VALUE;
+        		}
+        		break;
+
+      		case PS_SLICE_GROUP_MAP_TYPE_CHANGING_3:
+      		case PS_SLICE_GROUP_MAP_TYPE_CHANGING_4:
+      		case PS_SLICE_GROUP_MAP_TYPE_CHANGING_5:
+        		if ((retCode = u_n( bitbuf, 1, &pps->slice_group_change_direction_flag)) < 0)
+          			return retCode;
+        		if ((retCode = ue_v( bitbuf, &pps->slice_group_change_rate_minus1, MAX_PIC_SIZE_IN_MBS-1)) < 0)
+          			return retCode;
+        		break;
+
+      		case PS_SLICE_GROUP_MAP_TYPE_EXPLICIT:
+
+        		if ((retCode = ue_v( bitbuf, &pic_size_in_map_units_minus1, MAX_PIC_SIZE_IN_MBS-1 )) < 0)
+          			return retCode;
+
+        		// Allocate array for slice group ids if not already allocated 
+        		if (pic_size_in_map_units_minus1 != pps->pic_size_in_map_units_minus1) 
+        		{
+          			User::Free(pps->slice_group_id);
+
+          			pps->slice_group_id = (unsigned int *)User::Alloc( (pic_size_in_map_units_minus1+1) * sizeof(int));
+
+					if (pps->slice_group_id == 0)
+                        return PS_ERR_MEM_ALLOC;
+
+          			pps->pic_size_in_map_units_minus1 = pic_size_in_map_units_minus1;
+        		}
+
+        		// Calculate len = ceil( Log2( num_slice_groups_minus1 + 1 ) )
+        		tmp = pps->num_slice_groups_minus1 + 1;
+        		tmp = tmp >> 1;
+        		for( len = 0; len < 16 && tmp != 0; len++ )
+          			tmp >>= 1;
+        		
+        		if ( (((unsigned)1)<<len) < (pps->num_slice_groups_minus1 + 1) )
+          			len++;
+
+        		for( i = 0; i <= pps->pic_size_in_map_units_minus1; i++ ) 
+        		{
+          			if ((retCode = u_n( bitbuf, len, &pps->slice_group_id[i])) < 0)
+            			return retCode;
+        		}
+
+        		break;
+
+      		default:
+        		// Cannnot happen 
+        		break;
+    		}
+  	}
+
+  	if ((retCode = ue_v( bitbuf, &pps->num_ref_idx_l0_active_minus1, 31 )) < 0)
+    	return retCode;
+
+  	if ((retCode = ue_v( bitbuf, &pps->num_ref_idx_l1_active_minus1, 31 )) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n( bitbuf, 1, &pps->weighted_pred_flag)) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n( bitbuf, 2, &pps->weighted_bipred_idc)) < 0)
+    	return retCode;
+
+  	if (pps->weighted_bipred_idc > 2)
+    	return PS_ERR_ILLEGAL_VALUE;
+
+  	if ((retCode = se_v( bitbuf, &pps->pic_init_qp_minus26, -26, 25 )) < 0)
+    	return retCode;
+
+  	if ((retCode = se_v( bitbuf, &pps->pic_init_qs_minus26, -26, 25  )) < 0)
+    	return retCode;
+
+  	if ((retCode = se_v( bitbuf, &pps->chroma_qp_index_offset, -12, 12 )) < 0)
+    	return retCode;
+
+  	pps->chroma_qp_index_offset = clip(MIN_CHROMA_QP_INDEX, MAX_CHROMA_QP_INDEX, pps->chroma_qp_index_offset);
+
+  	if ((retCode = u_n( bitbuf, 1, &pps->deblocking_filter_parameters_present_flag )) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n( bitbuf, 1, &pps->constrained_intra_pred_flag )) < 0)
+    	return retCode;
+
+  	if ((retCode = u_n( bitbuf, 1, &pps->redundant_pic_cnt_present_flag )) < 0)
+    	return retCode;
+
+  	if (bibSkipTrailingBits(bitbuf) < 0)
+    	return PS_ERROR;
+
+  	// Store the size of the PPS set
+  	pps->PPSlength = bitbuf->bytePos;
+  
+	syncBitBufferBitpos(bitbuf);
+	
+  	// If we had a possible conflict, compare the PPS sets with the same id to see if only one PPS set can be used.
+  	if (possibleIdConflict)
+  	{
+		useOnePPS = ComparePPSSets(ppsList[pic_parameter_set_id],pps);
+
+	  	if (!useOnePPS)
+	  	{
+  			TUint trailingBits = GetNumTrailingBits(bitbuf);
+  			TInt diff = 0;
+			TUint oldPPSId = pic_parameter_set_id;
+			TUint oldIdLength = ReturnUnsignedExpGolombCodeLength(oldPPSId);
+			TUint newIdLength = ReturnUnsignedExpGolombCodeLength(newPPSId);
+
+	  		for (i=0; i<PS_MAX_NUM_OF_PPS; i++)
+  			{
+  				// Compared if a previously stored PPS might be used
+  				if (ppsList[i])
+					useOnePPS = ComparePPSSets(ppsList[i],pps);
+  			
+	  			if (useOnePPS)
+  				{
+  					// Check also that the SPS id's match
+				  	if ( modifySPSId )
+				  	{
+						if (spsList[pps->seq_parameter_set_id]->newSPSId != ppsList[i]->seq_parameter_set_id)
+							useOnePPS = 0;
+						else
+						{
+	  						// We can use this previously generated PPSId here also
+  							newPPSId = i;
+  							break;	
+						}
+				  	}
+				  	else
+				  	{
+						if (pps->seq_parameter_set_id != ppsList[i]->seq_parameter_set_id)
+							useOnePPS = 0;
+						else
+						{
+	  						// We can use this previously generated PPSId here also
+  							newPPSId = i;
+  							break;	
+						}
+				  	}
+  				}
+  			}
+		
+	  		if ( newPPSId > PS_MAX_NUM_OF_PPS )
+	  		{
+	  			// We have reached maximum number of PPS, return an error
+	  			return PS_ERROR;
+	  		}	
+	  	
+	    	(*aNumPPS)++;
+
+	  		// Set indexChanged to true and give the new index to old PPS, so that (new) slices can refer to the new PPS
+	  		ppsList[pic_parameter_set_id]->indexChanged = 1;
+	  		ppsList[pic_parameter_set_id]->newPPSId = newPPSId;	// The new Id
+	  	
+	  		if (aFrameFromEncoder)
+		  		ppsList[pic_parameter_set_id]->encPPSId = newPPSId;		// The new Id
+			else
+		  		ppsList[pic_parameter_set_id]->origPPSId = newPPSId;	// The new Id
+		  	
+	  		// Store the new PPS at the new index, unless we are using a previously stored PPS
+			if (!ppsList[newPPSId])
+		  		ppsList[newPPSId] = pps;
+  		
+			// Restore the bit buffer position at the PPS Id
+			bitbuf->bitpos = bitPosit;
+			bitbuf->bytePos = bytePosit;
+		
+			if(trailingBits > 8)
+			{	
+				trailingBits = 8;
+			}
+		
+			if ( oldIdLength == newIdLength )
+			{	
+				// Just encode the new Id on top of the old Id
+				bitbuf->bitpos += oldIdLength;
+				if (bitbuf->bitpos > 8)
+				{	
+					// Go to the right byte and bit position
+					bitbuf->bytePos -= bitbuf->bitpos / 8;
+					bitbuf->bitpos = bitbuf->bitpos % 8;
+				}
+				
+				EncodeUnsignedExpGolombCode(bitbuf, newPPSId);
+			}
+			else if ( oldIdLength < newIdLength )
+			{
+				diff = newIdLength - oldIdLength;
+			
+				// Adjust the PPS length
+				if (diff >= 8)
+				{
+					// Add as many extra bytes as is required
+					pps->PPSlength += (diff / 8);
+				}
+			
+				if ( trailingBits < (diff % 8) )
+				{
+					// Add one byte since there aren't enough trailing bits for the extra bits
+					pps->PPSlength += 1;
+				}
+			
+				ShiftBufferRight(bitbuf, diff, trailingBits, oldIdLength);
+
+				// After shifting, encode the new value to the bit buffer
+				EncodeUnsignedExpGolombCode(bitbuf, newPPSId);
+			}
+			else
+			{
+				// New id's length is smaller than old id's length
+				diff = oldIdLength - newIdLength;
+			
+				if (diff >= 8)
+				{
+					// Adjust the PPS length
+					pps->PPSlength -= (diff / 8);
+				}
+			
+				ShiftBufferLeft(bitbuf, diff, oldIdLength);
+			
+				// After shifting, encode the new value to the bit buffer
+				EncodeUnsignedExpGolombCode(bitbuf, newPPSId);
+			}
+
+	  		// Store the position of the bit buffer for possible SPS id modification
+  			// The right bit position is the current minus the size of the SPS id length
+  			bitSPSPosit = bitbuf->bitpos - ReturnUnsignedExpGolombCodeLength(pps->seq_parameter_set_id);
+  			byteSPSPosit = bitbuf->bytePos;
+  		
+  			if(bitSPSPosit < 1)
+  			{
+	  			byteSPSPosit++;
+  				bitSPSPosit += 8;
+  			}
+		}
+		else
+		{
+	  		// In case the index was changed for some earlier PPS, 
+	  		// reset the index changed value back to zero
+	  		ppsList[pic_parameter_set_id]->indexChanged = 0;
+		}
+  	}
+  
+  	if ( modifySPSId )
+  	{
+  		TUint trailingBits = GetNumTrailingBits(bitbuf);
+  		TInt diff = 0;
+
+		TUint oldSPSId = pps->seq_parameter_set_id;
+		TUint newSPSId = spsList[pps->seq_parameter_set_id]->newSPSId;
+		
+		TUint oldIdLength = ReturnUnsignedExpGolombCodeLength(oldSPSId);
+		TUint newIdLength = ReturnUnsignedExpGolombCodeLength(newSPSId);
+		
+		
+		// Restore the bit buffer position at the SPS Id
+		bitbuf->bitpos = bitSPSPosit;
+		bitbuf->bytePos = byteSPSPosit;
+		
+		if(trailingBits > 8)
+		{
+			trailingBits = 8;
+		}
+		
+		if ( oldIdLength == newIdLength )
+		{
+			// Just encode the new Id on top of the old Id
+			bitbuf->bitpos += oldIdLength;
+			if(bitbuf->bitpos > 8)
+			{	
+				// Go to the right byte and bit position
+				bitbuf->bytePos -= bitbuf->bitpos / 8;
+				bitbuf->bitpos = bitbuf->bitpos % 8;
+			}
+		
+			EncodeUnsignedExpGolombCode(bitbuf, newSPSId);
+		}
+		else if ( oldIdLength < newIdLength )
+		{
+			diff = newIdLength - oldIdLength;
+			
+			// Adjust the PPS length
+			if (diff >= 8)
+			{
+				// Add as many extra bytes as is required
+				pps->PPSlength += (diff / 8);
+			}
+		
+			if ( trailingBits < (diff % 8) )
+			{
+				// Add one byte since there aren't enough trailing bits for the extra bits
+				pps->PPSlength += 1;
+			}
+			
+			ShiftBufferRight(bitbuf, diff, trailingBits, oldIdLength);
+
+			// After shifting, encode the new value to the bit buffer
+			EncodeUnsignedExpGolombCode(bitbuf, newSPSId);
+			
+		}
+		else
+		{
+			// New id's length is smaller than old id's length
+			diff = oldIdLength - newIdLength;
+			
+			if (diff >= 8)
+			{
+				// Adjust the PPS length
+				pps->PPSlength -= (diff / 8);
+			}
+			
+			ShiftBufferLeft(bitbuf, diff, oldIdLength);
+			
+			// After shifting, encode the new value to the bit buffer
+			EncodeUnsignedExpGolombCode(bitbuf, newSPSId);
+		}
+  
+  		// Modify the SPS id in the pps
+  		pps->seq_parameter_set_id = newSPSId;	
+  	}
+  
+	if ( IsPPSSupported(pps) == KErrNotSupported )
+  		return KErrNotSupported;
+  
+  	
+  	// Allocate memory for the encoded PPS data in case we have a new PPS (i.e. a new original PPS or a PPS with a new index)  
+  	if ( !useOnePPS )
+  	{
+		// Store the buffer containing the PPS set in order to later pass it to the 3gpmp4library
+  		pps->codedPPSBuffer = (TUint8*) User::Alloc(pps->PPSlength);    
+
+		if (pps->codedPPSBuffer == 0)
+		    return PS_ERR_MEM_ALLOC;
+  
+  		for (i=0; i<pps->PPSlength; i++)
+  		{
+  			pps->codedPPSBuffer[i] = bitbuf->data[i];
+  		}
+  	}
+  	else if (possibleIdConflict)
+  	{
+  		// In case of conflicting id and one PPS, free the PPS allocated here
+	  	User::Free(pps);
+  	}
+
+  	return PS_OK;
+}
+
+#endif  // VIDEOEDITORENGINE_AVC_EDITING
+