root/libde265/vps.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_vps
  2. read_profile_tier_level
  3. dump_vps
  4. dump_profile_tier_level

/*
 * H.265 video codec.
 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
 *
 * This file is part of libde265.
 *
 * libde265 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * libde265 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with libde265.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "vps.h"
#include "util.h"
#include "decctx.h"

#include <assert.h>


de265_error read_vps(decoder_context* ctx, bitreader* reader, video_parameter_set* vps)
{
  int vlc;

  vps->video_parameter_set_id = vlc = get_bits(reader, 4);
  if (vlc >= DE265_MAX_VPS_SETS) return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;

  skip_bits(reader, 2);
  vps->vps_max_layers = vlc = get_bits(reader,6) +1;
  if (vlc != 1) return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; // TODO: out of specification

  vps->vps_max_sub_layers = vlc = get_bits(reader,3) +1;
  if (vlc >= MAX_TEMPORAL_SUBLAYERS) return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;

  vps->vps_temporal_id_nesting_flag = get_bits(reader,1);
  skip_bits(reader, 16);

  read_profile_tier_level(reader, &vps->profile_tier_level,
                          vps->vps_max_sub_layers);

  /*
  read_bit_rate_pic_rate_info(reader, &vps->bit_rate_pic_rate_info,
                              0, vps->vps_max_sub_layers-1);
  */

  vps->vps_sub_layer_ordering_info_present_flag = get_bits(reader,1);
  //assert(vps->vps_max_sub_layers-1 < MAX_TEMPORAL_SUBLAYERS);

  int firstLayerRead = vps->vps_sub_layer_ordering_info_present_flag ? 0 : (vps->vps_max_sub_layers-1);

  for (int i=firstLayerRead;i<vps->vps_max_sub_layers;i++) {
    vps->layer[i].vps_max_dec_pic_buffering = get_uvlc(reader);
    vps->layer[i].vps_max_num_reorder_pics  = get_uvlc(reader);
    vps->layer[i].vps_max_latency_increase  = get_uvlc(reader);
  }

  if (!vps->vps_sub_layer_ordering_info_present_flag) {
    assert(firstLayerRead < MAX_TEMPORAL_SUBLAYERS);

    for (int i=0;i<firstLayerRead;i++) {
      vps->layer[i].vps_max_dec_pic_buffering = vps->layer[firstLayerRead].vps_max_dec_pic_buffering;
      vps->layer[i].vps_max_num_reorder_pics  = vps->layer[firstLayerRead].vps_max_num_reorder_pics;
      vps->layer[i].vps_max_latency_increase  = vps->layer[firstLayerRead].vps_max_latency_increase;
    }
  }


  vps->vps_max_layer_id = get_bits(reader,6);
  vps->vps_num_layer_sets = get_uvlc(reader)+1;

  if (vps->vps_num_layer_sets<0 ||
      vps->vps_num_layer_sets>=1024) {
    ctx->add_warning(DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE, false);
    return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
  }

  for (int i=1; i <= vps->vps_num_layer_sets-1; i++)
    for (int j=0; j <= vps->vps_max_layer_id; j++)
      {
        vps->layer_id_included_flag[i][j] = get_bits(reader,1);
      }

  vps->vps_timing_info_present_flag = get_bits(reader,1);

  if (vps->vps_timing_info_present_flag) {
    vps->vps_num_units_in_tick = get_bits(reader,32);
    vps->vps_time_scale        = get_bits(reader,32);
    vps->vps_poc_proportional_to_timing_flag = get_bits(reader,1);

    if (vps->vps_poc_proportional_to_timing_flag) {
      vps->vps_num_ticks_poc_diff_one = get_uvlc(reader)+1;
      vps->vps_num_hrd_parameters     = get_uvlc(reader);

      if (vps->vps_num_hrd_parameters >= 1024) {
        assert(false); // TODO: return bitstream error
      }

      for (int i=0; i<vps->vps_num_hrd_parameters; i++) {
        vps->hrd_layer_set_idx[i] = get_uvlc(reader);

        if (i > 0) {
          vps->cprms_present_flag[i] = get_bits(reader,1);
        }

        //hrd_parameters(cprms_present_flag[i], vps_max_sub_layers_minus1)

        return DE265_OK; // TODO: decode hrd_parameters()
      }
    }
  }
  
  vps->vps_extension_flag = get_bits(reader,1);

  if (vps->vps_extension_flag) {
    /*
    while( more_rbsp_data() )
    vps_extension_data_flag u(1)
    rbsp_trailing_bits()
    */
  }

  return DE265_OK;
}


void read_profile_tier_level(bitreader* reader,
                             struct profile_tier_level* hdr,
                             int max_sub_layers)
{
  hdr->general_profile_space = get_bits(reader,2);
  hdr->general_tier_flag = get_bits(reader,1);
  hdr->general_profile_idc = get_bits(reader,5);

  for (int i=0; i<32; i++) {
    hdr->general_profile_compatibility_flag[i] = get_bits(reader,1);
  }

  hdr->general_progressive_source_flag = get_bits(reader,1);
  hdr->general_interlaced_source_flag  = get_bits(reader,1);
  hdr->general_non_packed_constraint_flag = get_bits(reader,1);
  hdr->general_frame_only_constraint_flag = get_bits(reader,1);
  skip_bits(reader,44);

  hdr->general_level_idc = get_bits(reader,8);


  for (int i=0; i<max_sub_layers-1; i++)
    {
      hdr->profile[i].sub_layer_profile_present_flag = get_bits(reader,1);
      hdr->profile[i].sub_layer_level_present_flag   = get_bits(reader,1);
    }

  if (max_sub_layers > 1)
    {
      for (int i=max_sub_layers-1; i<8; i++)
        {
          skip_bits(reader,2);
        }
    }

  for (int i=0; i<max_sub_layers-1; i++)
    {
      if (hdr->profile[i].sub_layer_profile_present_flag)
        {
          hdr->profile[i].sub_layer_profile_space = get_bits(reader,2);
          hdr->profile[i].sub_layer_tier_flag = get_bits(reader,1);
          hdr->profile[i].sub_layer_profile_idc = get_bits(reader,5);

          for (int j=0; j<32; j++)
            {
              hdr->profile[i].sub_layer_profile_compatibility_flag[j] = get_bits(reader,1);
            }

          hdr->profile[i].sub_layer_progressive_source_flag = get_bits(reader,1);
          hdr->profile[i].sub_layer_interlaced_source_flag  = get_bits(reader,1);
          hdr->profile[i].sub_layer_non_packed_constraint_flag = get_bits(reader,1);
          hdr->profile[i].sub_layer_frame_only_constraint_flag = get_bits(reader,1);
          skip_bits(reader,44);
        }

      if (hdr->profile[i].sub_layer_level_present_flag)
        {
          hdr->profile[i].sub_layer_level_idc = get_bits(reader,8);
        }
    }
}


/*
void read_bit_rate_pic_rate_info(bitreader* reader,
                                 struct bit_rate_pic_rate_info* hdr,
                                 int TempLevelLow,
                                 int TempLevelHigh)
{
  for (int i=TempLevelLow; i<=TempLevelHigh; i++) {

    hdr->bit_rate_info_present_flag[i] = get_bits(reader,1);
    hdr->pic_rate_info_present_flag[i] = get_bits(reader,1);

    if (hdr->bit_rate_info_present_flag[i]) {
      hdr->avg_bit_rate[i] = get_bits(reader,16);
      hdr->max_bit_rate[i] = get_bits(reader,16);
    }

    if (hdr->pic_rate_info_present_flag[i]) {
      hdr->constant_pic_rate_idc[i] = get_bits(reader,2);
      hdr->avg_pic_rate[i] = get_bits(reader,16);
    }
  }
}
*/



#define LOG0(t) log2fh(fh, t)
#define LOG1(t,d) log2fh(fh, t,d)
#define LOG2(t,d1,d2) log2fh(fh, t,d1,d2)
#define LOG3(t,d1,d2,d3) log2fh(fh, t,d1,d2,d3)

void dump_vps(video_parameter_set* vps, int fd)
{
  FILE* fh;
  if (fd==1) fh=stdout;
  else if (fd==2) fh=stderr;
  else { return; }

  LOG0("----------------- VPS -----------------\n");
  LOG1("video_parameter_set_id                : %d\n", vps->video_parameter_set_id);
  LOG1("vps_max_layers                        : %d\n", vps->vps_max_layers);
  LOG1("vps_max_sub_layers                    : %d\n", vps->vps_max_sub_layers);
  LOG1("vps_temporal_id_nesting_flag          : %d\n", vps->vps_temporal_id_nesting_flag);

  dump_profile_tier_level(&vps->profile_tier_level, vps->vps_max_sub_layers, fh);
  //dump_bit_rate_pic_rate_info(&vps->bit_rate_pic_rate_info, 0, vps->vps_max_sub_layers-1);

  LOG1("vps_sub_layer_ordering_info_present_flag : %d\n",
       vps->vps_sub_layer_ordering_info_present_flag);

  if (vps->vps_sub_layer_ordering_info_present_flag) {
    for (int i=0;i<vps->vps_max_sub_layers;i++) {
      LOG2("layer %d: vps_max_dec_pic_buffering = %d\n",i,vps->layer[i].vps_max_dec_pic_buffering);
      LOG1("         vps_max_num_reorder_pics  = %d\n",vps->layer[i].vps_max_num_reorder_pics);
      LOG1("         vps_max_latency_increase  = %d\n",vps->layer[i].vps_max_latency_increase);
    }
  }
  else {
    LOG1("layer (all): vps_max_dec_pic_buffering = %d\n",vps->layer[0].vps_max_dec_pic_buffering);
    LOG1("             vps_max_num_reorder_pics  = %d\n",vps->layer[0].vps_max_num_reorder_pics);
    LOG1("             vps_max_latency_increase  = %d\n",vps->layer[0].vps_max_latency_increase);
  }


  LOG1("vps_max_layer_id   = %d\n", vps->vps_max_layer_id);
  LOG1("vps_num_layer_sets = %d\n", vps->vps_num_layer_sets);

  for (int i=1; i <= vps->vps_num_layer_sets-1; i++)
    for (int j=0; j <= vps->vps_max_layer_id; j++)
      {
        LOG3("layer_id_included_flag[%d][%d] = %d\n",i,j,
             vps->layer_id_included_flag[i][j]);
      }

  LOG1("vps_timing_info_present_flag = %d\n",
       vps->vps_timing_info_present_flag);

  if (vps->vps_timing_info_present_flag) {
    LOG1("vps_num_units_in_tick = %d\n", vps->vps_num_units_in_tick);
    LOG1("vps_time_scale        = %d\n", vps->vps_time_scale);
    LOG1("vps_poc_proportional_to_timing_flag = %d\n", vps->vps_poc_proportional_to_timing_flag);

    if (vps->vps_poc_proportional_to_timing_flag) {
      LOG1("vps_num_ticks_poc_diff_one = %d\n", vps->vps_num_ticks_poc_diff_one);
      LOG1("vps_num_hrd_parameters     = %d\n", vps->vps_num_hrd_parameters);

      for (int i=0; i<vps->vps_num_hrd_parameters; i++) {
        LOG2("hrd_layer_set_idx[%d] = %d\n", i, vps->hrd_layer_set_idx[i]);

        if (i > 0) {
          LOG2("cprms_present_flag[%d] = %d\n", i, vps->cprms_present_flag[i]);
        }

        //hrd_parameters(cprms_present_flag[i], vps_max_sub_layers_minus1)

        return; // TODO: decode hrd_parameters()
      }
    }
  }
  
  LOG1("vps_extension_flag = %d\n", vps->vps_extension_flag);
}


void dump_profile_tier_level(const struct profile_tier_level* hdr,
                             int max_sub_layers, FILE* fh)
{
  LOG1("  general_profile_space     : %d\n", hdr->general_profile_space);
  LOG1("  general_tier_flag         : %d\n", hdr->general_tier_flag);
  LOG1("  general_profile_idc       : %d\n", hdr->general_profile_idc);

  LOG0("  general_profile_compatibility_flags: ");
  for (int i=0; i<32; i++) {
    if (i) LOG0("*,");
    LOG1("*%d",hdr->general_profile_compatibility_flag[i]);
  }
  LOG0("*\n");

  LOG1("  general_level_idc         : %d\n", hdr->general_level_idc);

  for (int i=0; i<max_sub_layers-1; i++)
    {
      LOG1("  Profile/Tier/Level [Layer %d]\n",i);

      if (hdr->profile[i].sub_layer_profile_present_flag) {

        LOG1("    sub_layer_profile_space : %d\n",hdr->profile[i].sub_layer_profile_space);
        LOG1("    sub_layer_tier_flag     : %d\n",hdr->profile[i].sub_layer_tier_flag);
        LOG1("    sub_layer_profile_idc   : %d\n",hdr->profile[i].sub_layer_profile_idc);

        LOG0("    sub_layer_profile_compatibility_flags: ");
        for (int j=0; j<32; j++) {
          if (j) LOG0(",");
          LOG1("%d",hdr->profile[i].sub_layer_profile_compatibility_flag[j]);
        }
        LOG0("\n");

        LOG1("    sub_layer_progressive_source_flag : %d\n",hdr->profile[i].sub_layer_progressive_source_flag);
        LOG1("    sub_layer_interlaced_source_flag : %d\n",hdr->profile[i].sub_layer_interlaced_source_flag);
        LOG1("    sub_layer_non_packed_constraint_flag : %d\n",hdr->profile[i].sub_layer_non_packed_constraint_flag);
        LOG1("    sub_layer_frame_only_constraint_flag : %d\n",hdr->profile[i].sub_layer_frame_only_constraint_flag);
      }


      if (hdr->profile[i].sub_layer_level_present_flag) {
        LOG1("    sub_layer_level_idc   : %d\n", hdr->profile[i].sub_layer_level_idc);
      }
    }
}

#undef LOG0
#undef LOG1
#undef LOG2
#undef LOG3


/*
void dump_bit_rate_pic_rate_info(struct bit_rate_pic_rate_info* hdr,
                                 int TempLevelLow,
                                 int TempLevelHigh)
{
  for (int i=TempLevelLow; i<=TempLevelHigh; i++) {

    LOG("  Bitrate [Layer %d]\n", i);

    if (hdr->bit_rate_info_present_flag[i]) {
      LOG("    avg_bit_rate : %d\n", hdr->avg_bit_rate[i]);
      LOG("    max_bit_rate : %d\n", hdr->max_bit_rate[i]);
    }

    if (hdr->pic_rate_info_present_flag[i]) {
      LOG("    constant_pic_rate_idc : %d\n", hdr->constant_pic_rate_idc[i]);
      LOG("    avg_pic_rate[i]       : %d\n", hdr->avg_pic_rate[i]);
    }
  }
}
*/

/* [<][>][^][v][top][bottom][index][help] */