summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRodeo <[email protected]>2014-03-13 01:36:22 +0000
committerRodeo <[email protected]>2014-03-13 01:36:22 +0000
commit042db50b62739c9a01ed83e225926dbe1de9b843 (patch)
tree9fd5889fb7e16a564af87bd8447791a431aa2d32
parent74bc2e472c901e75412dd82845e6cc16277eff1d (diff)
x265: enable MP4 and Matroska muxing.
Also remove the raw muxer. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6105 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--contrib/ffmpeg/A02-hevcmux.patch1411
-rw-r--r--libhb/common.c7
-rw-r--r--libhb/common.h1
-rw-r--r--libhb/encx265.c34
-rw-r--r--libhb/muxcommon.c4
5 files changed, 1412 insertions, 45 deletions
diff --git a/contrib/ffmpeg/A02-hevcmux.patch b/contrib/ffmpeg/A02-hevcmux.patch
new file mode 100644
index 000000000..ddbc494eb
--- /dev/null
+++ b/contrib/ffmpeg/A02-hevcmux.patch
@@ -0,0 +1,1411 @@
+diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h
+index efe5059..ce3500f 100644
+--- a/libavcodec/golomb.h
++++ b/libavcodec/golomb.h
+@@ -206,6 +206,18 @@ static inline int get_se_golomb(GetBitContext *gb)
+ }
+ }
+
++static inline int get_se_golomb_long(GetBitContext *gb)
++{
++ unsigned int buf = get_ue_golomb_long(gb);
++
++ if (buf & 1)
++ buf = -(buf >> 1);
++ else
++ buf = (buf >> 1);
++
++ return buf;
++}
++
+ static inline int svq3_get_se_golomb(GetBitContext *gb)
+ {
+ unsigned int buf;
+diff --git a/libavformat/Makefile b/libavformat/Makefile
+index d491d43..5694314 100644
+--- a/libavformat/Makefile
++++ b/libavformat/Makefile
+@@ -168,7 +168,7 @@ OBJS-$(CONFIG_M4V_MUXER) += rawenc.o
+ OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \
+ isom.o rmsipr.o
+ OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \
+- isom.o avc.o \
++ isom.o avc.o hevc.o \
+ flacenc_header.o avlanguage.o wv.o
+ OBJS-$(CONFIG_MD5_MUXER) += md5enc.o
+ OBJS-$(CONFIG_MJPEG_DEMUXER) += rawdec.o
+@@ -179,7 +179,7 @@ OBJS-$(CONFIG_MM_DEMUXER) += mm.o
+ OBJS-$(CONFIG_MMF_DEMUXER) += mmf.o pcm.o
+ OBJS-$(CONFIG_MMF_MUXER) += mmf.o
+ OBJS-$(CONFIG_MOV_DEMUXER) += mov.o isom.o mov_chan.o
+-OBJS-$(CONFIG_MOV_MUXER) += movenc.o isom.o avc.o \
++OBJS-$(CONFIG_MOV_MUXER) += movenc.o isom.o avc.o hevc.o \
+ movenchint.o mov_chan.o
+ OBJS-$(CONFIG_MP2_MUXER) += mp3enc.o rawenc.o id3v2enc.o
+ OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o
+diff --git a/libavformat/hevc.c b/libavformat/hevc.c
+new file mode 100644
+index 0000000..37b35b4
+--- /dev/null
++++ b/libavformat/hevc.c
+@@ -0,0 +1,1140 @@
++/*
++ * Copyright (c) 2014 Tim Walker <[email protected]>
++ *
++ * This file is part of Libav.
++ *
++ * Libav 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 2.1 of the License, or (at your option) any later version.
++ *
++ * Libav 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 Libav; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "libavcodec/get_bits.h"
++#include "libavcodec/golomb.h"
++#include "libavcodec/hevc.h"
++#include "libavutil/intreadwrite.h"
++#include "avc.h"
++#include "avio.h"
++#include "hevc.h"
++
++#define MAX_SPATIAL_SEGMENTATION 4096 // max. value of u(12) field
++
++typedef struct HVCCNALUnitArray {
++ uint8_t array_completeness;
++ uint8_t NAL_unit_type;
++ uint16_t numNalus;
++ uint16_t *nalUnitLength;
++ uint8_t **nalUnit;
++} HVCCNALUnitArray;
++
++typedef struct HEVCDecoderConfigurationRecord {
++ uint8_t configurationVersion;
++ uint8_t general_profile_space;
++ uint8_t general_tier_flag;
++ uint8_t general_profile_idc;
++ uint32_t general_profile_compatibility_flags;
++ uint64_t general_constraint_indicator_flags;
++ uint8_t general_level_idc;
++ uint16_t min_spatial_segmentation_idc;
++ uint8_t parallelismType;
++ uint8_t chromaFormat;
++ uint8_t bitDepthLumaMinus8;
++ uint8_t bitDepthChromaMinus8;
++ uint16_t avgFrameRate;
++ uint8_t constantFrameRate;
++ uint8_t numTemporalLayers;
++ uint8_t temporalIdNested;
++ uint8_t lengthSizeMinusOne;
++ uint8_t numOfArrays;
++ HVCCNALUnitArray *array;
++} HEVCDecoderConfigurationRecord;
++
++typedef struct HVCCProfileTierLevel {
++ uint8_t profile_space;
++ uint8_t tier_flag;
++ uint8_t profile_idc;
++ uint32_t profile_compatibility_flags;
++ uint64_t constraint_indicator_flags;
++ uint8_t level_idc;
++} HVCCProfileTierLevel;
++
++static void hvcc_update_ptl(HEVCDecoderConfigurationRecord *hvcc,
++ HVCCProfileTierLevel *ptl)
++{
++ /*
++ * The value of general_profile_space in all the parameter sets must be
++ * identical.
++ */
++ hvcc->general_profile_space = ptl->profile_space;
++
++ /*
++ * The level indication general_level_idc must indicate a level of
++ * capability equal to or greater than the highest level indicated for the
++ * highest tier in all the parameter sets.
++ */
++ if (hvcc->general_tier_flag < ptl->tier_flag)
++ hvcc->general_level_idc = ptl->level_idc;
++ else
++ hvcc->general_level_idc = FFMAX(hvcc->general_level_idc, ptl->level_idc);
++
++ /*
++ * The tier indication general_tier_flag must indicate a tier equal to or
++ * greater than the highest tier indicated in all the parameter sets.
++ */
++ hvcc->general_tier_flag = FFMAX(hvcc->general_tier_flag, ptl->tier_flag);
++
++ /*
++ * The profile indication general_profile_idc must indicate a profile to
++ * which the stream associated with this configuration record conforms.
++ *
++ * If the sequence parameter sets are marked with different profiles, then
++ * the stream may need examination to determine which profile, if any, the
++ * entire stream conforms to. If the entire stream is not examined, or the
++ * examination reveals that there is no profile to which the entire stream
++ * conforms, then the entire stream must be split into two or more
++ * sub-streams with separate configuration records in which these rules can
++ * be met.
++ *
++ * Note: set the profile to the highest value for the sake of simplicity.
++ */
++ hvcc->general_profile_idc = FFMAX(hvcc->general_profile_idc, ptl->profile_idc);
++
++ /*
++ * Each bit in general_profile_compatibility_flags may only be set if all
++ * the parameter sets set that bit.
++ */
++ hvcc->general_profile_compatibility_flags &= ptl->profile_compatibility_flags;
++
++ /*
++ * Each bit in general_constraint_indicator_flags may only be set if all
++ * the parameter sets set that bit.
++ */
++ hvcc->general_constraint_indicator_flags &= ptl->constraint_indicator_flags;
++}
++
++static void hvcc_parse_ptl(GetBitContext *gb,
++ HEVCDecoderConfigurationRecord *hvcc,
++ unsigned int max_sub_layers_minus1)
++{
++ unsigned int i;
++ HVCCProfileTierLevel general_ptl;
++ uint8_t sub_layer_profile_present_flag[MAX_SUB_LAYERS];
++ uint8_t sub_layer_level_present_flag[MAX_SUB_LAYERS];
++
++ general_ptl.profile_space = get_bits(gb, 2);
++ general_ptl.tier_flag = get_bits1(gb);
++ general_ptl.profile_idc = get_bits(gb, 5);
++ general_ptl.profile_compatibility_flags = get_bits_long(gb, 32);
++ general_ptl.constraint_indicator_flags = get_bits64(gb, 48);
++ general_ptl.level_idc = get_bits(gb, 8);
++ hvcc_update_ptl(hvcc, &general_ptl);
++
++ for (i = 0; i < max_sub_layers_minus1; i++) {
++ sub_layer_profile_present_flag[i] = get_bits1(gb);
++ sub_layer_level_present_flag[i] = get_bits1(gb);
++ }
++
++ if (max_sub_layers_minus1 > 0)
++ for (i = max_sub_layers_minus1; i < 8; i++)
++ skip_bits(gb, 2); // reserved_zero_2bits[i]
++
++ for (i = 0; i < max_sub_layers_minus1; i++) {
++ if (sub_layer_profile_present_flag[i]) {
++ /*
++ * sub_layer_profile_space[i] u(2)
++ * sub_layer_tier_flag[i] u(1)
++ * sub_layer_profile_idc[i] u(5)
++ * sub_layer_profile_compatibility_flag[i][0..31] u(32)
++ * sub_layer_progressive_source_flag[i] u(1)
++ * sub_layer_interlaced_source_flag[i] u(1)
++ * sub_layer_non_packed_constraint_flag[i] u(1)
++ * sub_layer_frame_only_constraint_flag[i] u(1)
++ * sub_layer_reserved_zero_44bits[i] u(44)
++ */
++ skip_bits_long(gb, 32);
++ skip_bits_long(gb, 32);
++ skip_bits (gb, 24);
++ }
++
++ if (sub_layer_level_present_flag[i])
++ skip_bits(gb, 8);
++ }
++}
++
++static void skip_sub_layer_hrd_parameters(GetBitContext *gb,
++ unsigned int cpb_cnt_minus1,
++ uint8_t sub_pic_hrd_params_present_flag)
++{
++ unsigned int i;
++
++ for (i = 0; i <= cpb_cnt_minus1; i++) {
++ get_ue_golomb_long(gb); // bit_rate_value_minus1
++ get_ue_golomb_long(gb); // cpb_size_value_minus1
++
++ if (sub_pic_hrd_params_present_flag) {
++ get_ue_golomb_long(gb); // cpb_size_du_value_minus1
++ get_ue_golomb_long(gb); // bit_rate_du_value_minus1
++ }
++
++ skip_bits1(gb); // cbr_flag
++ }
++}
++
++static void skip_hrd_parameters(GetBitContext *gb, uint8_t cprms_present_flag,
++ unsigned int max_sub_layers_minus1)
++{
++ unsigned int i;
++ uint8_t sub_pic_hrd_params_present_flag = 0;
++ uint8_t nal_hrd_parameters_present_flag = 0;
++ uint8_t vcl_hrd_parameters_present_flag = 0;
++
++ if (cprms_present_flag) {
++ nal_hrd_parameters_present_flag = get_bits1(gb);
++ vcl_hrd_parameters_present_flag = get_bits1(gb);
++
++ if (nal_hrd_parameters_present_flag ||
++ vcl_hrd_parameters_present_flag) {
++ sub_pic_hrd_params_present_flag = get_bits1(gb);
++
++ if (sub_pic_hrd_params_present_flag)
++ /*
++ * tick_divisor_minus2 u(8)
++ * du_cpb_removal_delay_increment_length_minus1 u(5)
++ * sub_pic_cpb_params_in_pic_timing_sei_flag u(1)
++ * dpb_output_delay_du_length_minus1 u(5)
++ */
++ skip_bits(gb, 19);
++
++ /*
++ * bit_rate_scale u(4)
++ * cpb_size_scale u(4)
++ */
++ skip_bits(gb, 8);
++
++ if (sub_pic_hrd_params_present_flag)
++ skip_bits(gb, 4); // cpb_size_du_scale
++
++ /*
++ * initial_cpb_removal_delay_length_minus1 u(5)
++ * au_cpb_removal_delay_length_minus1 u(5)
++ * dpb_output_delay_length_minus1 u(5)
++ */
++ skip_bits(gb, 15);
++ }
++ }
++
++ for (i = 0; i <= max_sub_layers_minus1; i++) {
++ unsigned int cpb_cnt_minus1 = 0;
++ uint8_t low_delay_hrd_flag = 0;
++ uint8_t fixed_pic_rate_within_cvs_flag = 0;
++ uint8_t fixed_pic_rate_general_flag = get_bits1(gb);
++
++ if (!fixed_pic_rate_general_flag)
++ fixed_pic_rate_within_cvs_flag = get_bits1(gb);
++
++ if (fixed_pic_rate_within_cvs_flag)
++ get_ue_golomb_long(gb); // elemental_duration_in_tc_minus1
++ else
++ low_delay_hrd_flag = get_bits1(gb);
++
++ if (!low_delay_hrd_flag)
++ cpb_cnt_minus1 = get_ue_golomb_long(gb);
++
++ if (nal_hrd_parameters_present_flag)
++ skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1,
++ sub_pic_hrd_params_present_flag);
++
++ if (vcl_hrd_parameters_present_flag)
++ skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1,
++ sub_pic_hrd_params_present_flag);
++ }
++}
++
++static void skip_timing_info(GetBitContext *gb)
++{
++ skip_bits_long(gb, 32); // num_units_in_tick
++ skip_bits_long(gb, 32); // time_scale
++
++ if (get_bits1(gb)) // poc_proportional_to_timing_flag
++ get_ue_golomb_long(gb); // num_ticks_poc_diff_one_minus1
++}
++
++static void hvcc_parse_vui(GetBitContext *gb,
++ HEVCDecoderConfigurationRecord *hvcc,
++ unsigned int max_sub_layers_minus1)
++{
++ unsigned int min_spatial_segmentation_idc;
++
++ if (get_bits1(gb)) // aspect_ratio_info_present_flag
++ if (get_bits(gb, 8) == 255) // aspect_ratio_idc
++ skip_bits_long(gb, 32); // sar_width u(16), sar_height u(16)
++
++ if (get_bits1(gb)) // overscan_info_present_flag
++ skip_bits1(gb); // overscan_appropriate_flag
++
++ if (get_bits1(gb)) { // video_signal_type_present_flag
++ skip_bits(gb, 4); // video_format u(3), video_full_range_flag u(1)
++
++ if (get_bits1(gb)) // colour_description_present_flag
++ /*
++ * colour_primaries u(8)
++ * transfer_characteristics u(8)
++ * matrix_coeffs u(8)
++ */
++ skip_bits(gb, 24);
++ }
++
++ if (get_bits1(gb)) { // chroma_loc_info_present_flag
++ get_ue_golomb_long(gb); // chroma_sample_loc_type_top_field
++ get_ue_golomb_long(gb); // chroma_sample_loc_type_bottom_field
++ }
++
++ /*
++ * neutral_chroma_indication_flag u(1)
++ * field_seq_flag u(1)
++ * frame_field_info_present_flag u(1)
++ */
++ skip_bits(gb, 3);
++
++ if (get_bits1(gb)) { // default_display_window_flag
++ get_ue_golomb_long(gb); // def_disp_win_left_offset
++ get_ue_golomb_long(gb); // def_disp_win_right_offset
++ get_ue_golomb_long(gb); // def_disp_win_top_offset
++ get_ue_golomb_long(gb); // def_disp_win_bottom_offset
++ }
++
++ if (get_bits1(gb)) { // vui_timing_info_present_flag
++ skip_timing_info(gb);
++
++ if (get_bits1(gb)) // vui_hrd_parameters_present_flag
++ skip_hrd_parameters(gb, 1, max_sub_layers_minus1);
++ }
++
++ if (get_bits1(gb)) { // bitstream_restriction_flag
++ /*
++ * tiles_fixed_structure_flag u(1)
++ * motion_vectors_over_pic_boundaries_flag u(1)
++ * restricted_ref_pic_lists_flag u(1)
++ */
++ skip_bits(gb, 3);
++
++ min_spatial_segmentation_idc = get_ue_golomb_long(gb);
++
++ /*
++ * unsigned int(12) min_spatial_segmentation_idc;
++ *
++ * The min_spatial_segmentation_idc indication must indicate a level of
++ * spatial segmentation equal to or less than the lowest level of
++ * spatial segmentation indicated in all the parameter sets.
++ */
++ hvcc->min_spatial_segmentation_idc = FFMIN(hvcc->min_spatial_segmentation_idc,
++ min_spatial_segmentation_idc);
++
++ get_ue_golomb_long(gb); // max_bytes_per_pic_denom
++ get_ue_golomb_long(gb); // max_bits_per_min_cu_denom
++ get_ue_golomb_long(gb); // log2_max_mv_length_horizontal
++ get_ue_golomb_long(gb); // log2_max_mv_length_vertical
++ }
++}
++
++static void skip_sub_layer_ordering_info(GetBitContext *gb)
++{
++ get_ue_golomb_long(gb); // max_dec_pic_buffering_minus1
++ get_ue_golomb_long(gb); // max_num_reorder_pics
++ get_ue_golomb_long(gb); // max_latency_increase_plus1
++}
++
++static int hvcc_parse_vps(GetBitContext *gb,
++ HEVCDecoderConfigurationRecord *hvcc)
++{
++ unsigned int vps_max_sub_layers_minus1;
++
++ /*
++ * vps_video_parameter_set_id u(4)
++ * vps_reserved_three_2bits u(2)
++ * vps_max_layers_minus1 u(6)
++ */
++ skip_bits(gb, 12);
++
++ vps_max_sub_layers_minus1 = get_bits(gb, 3);
++
++ /*
++ * numTemporalLayers greater than 1 indicates that the stream to which this
++ * configuration record applies is temporally scalable and the contained
++ * number of temporal layers (also referred to as temporal sub-layer or
++ * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1
++ * indicates that the stream is not temporally scalable. Value 0 indicates
++ * that it is unknown whether the stream is temporally scalable.
++ */
++ hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
++ vps_max_sub_layers_minus1 + 1);
++
++ /*
++ * vps_temporal_id_nesting_flag u(1)
++ * vps_reserved_0xffff_16bits u(16)
++ */
++ skip_bits(gb, 17);
++
++ hvcc_parse_ptl(gb, hvcc, vps_max_sub_layers_minus1);
++
++ /* nothing useful for hvcC past this point */
++ return 0;
++}
++
++static void skip_scaling_list_data(GetBitContext *gb)
++{
++ int i, j, k, num_coeffs;
++
++ for (i = 0; i < 4; i++)
++ for (j = 0; j < (i == 3 ? 2 : 6); j++)
++ if (!get_bits1(gb)) // scaling_list_pred_mode_flag[i][j]
++ get_ue_golomb_long(gb); // scaling_list_pred_matrix_id_delta[i][j]
++ else {
++ num_coeffs = FFMIN(64, 1 << (4 + (i << 1)));
++
++ if (i > 1)
++ get_se_golomb_long(gb); // scaling_list_dc_coef_minus8[i-2][j]
++
++ for (k = 0; k < num_coeffs; k++)
++ get_se_golomb_long(gb); // scaling_list_delta_coef
++ }
++}
++
++static int parse_rps(GetBitContext *gb, unsigned int rps_idx,
++ unsigned int num_rps,
++ unsigned int num_delta_pocs[MAX_SHORT_TERM_RPS_COUNT])
++{
++ unsigned int i;
++
++ if (rps_idx && get_bits1(gb)) { // inter_ref_pic_set_prediction_flag
++ /* this should only happen for slice headers, and this isn't one */
++ if (rps_idx >= num_rps)
++ return AVERROR_INVALIDDATA;
++
++ skip_bits1 (gb); // delta_rps_sign
++ get_ue_golomb_long(gb); // abs_delta_rps_minus1
++
++ num_delta_pocs[rps_idx] = 0;
++
++ /*
++ * From libavcodec/hevc_ps.c:
++ *
++ * if (is_slice_header) {
++ * //foo
++ * } else
++ * rps_ridx = &sps->st_rps[rps - sps->st_rps - 1];
++ *
++ * where:
++ * rps: &sps->st_rps[rps_idx]
++ * sps->st_rps: &sps->st_rps[0]
++ * is_slice_header: rps_idx == num_rps
++ *
++ * thus:
++ * if (num_rps != rps_idx)
++ * rps_ridx = &sps->st_rps[rps_idx - 1];
++ *
++ * NumDeltaPocs[RefRpsIdx]: num_delta_pocs[rps_idx - 1]
++ */
++ for (i = 0; i < num_delta_pocs[rps_idx - 1]; i++) {
++ uint8_t use_delta_flag = 0;
++ uint8_t used_by_curr_pic_flag = get_bits1(gb);
++ if (!used_by_curr_pic_flag)
++ use_delta_flag = get_bits1(gb);
++
++ if (used_by_curr_pic_flag || use_delta_flag)
++ num_delta_pocs[rps_idx]++;
++ }
++ } else {
++ unsigned int num_negative_pics = get_ue_golomb_long(gb);
++ unsigned int num_positive_pics = get_ue_golomb_long(gb);
++
++ num_delta_pocs[rps_idx] = num_negative_pics + num_positive_pics;
++
++ for (i = 0; i < num_negative_pics; i++) {
++ get_ue_golomb_long(gb); // delta_poc_s0_minus1[rps_idx]
++ skip_bits1 (gb); // used_by_curr_pic_s0_flag[rps_idx]
++ }
++
++ for (i = 0; i < num_positive_pics; i++) {
++ get_ue_golomb_long(gb); // delta_poc_s1_minus1[rps_idx]
++ skip_bits1 (gb); // used_by_curr_pic_s1_flag[rps_idx]
++ }
++ }
++
++ return 0;
++}
++
++static int hvcc_parse_sps(GetBitContext *gb,
++ HEVCDecoderConfigurationRecord *hvcc)
++{
++ unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4;
++ unsigned int num_short_term_ref_pic_sets, num_delta_pocs[MAX_SHORT_TERM_RPS_COUNT];
++
++ skip_bits(gb, 4); // sps_video_parameter_set_id
++
++ sps_max_sub_layers_minus1 = get_bits (gb, 3);
++
++ /*
++ * numTemporalLayers greater than 1 indicates that the stream to which this
++ * configuration record applies is temporally scalable and the contained
++ * number of temporal layers (also referred to as temporal sub-layer or
++ * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1
++ * indicates that the stream is not temporally scalable. Value 0 indicates
++ * that it is unknown whether the stream is temporally scalable.
++ */
++ hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers,
++ sps_max_sub_layers_minus1 + 1);
++
++ hvcc->temporalIdNested = get_bits1(gb);
++
++ hvcc_parse_ptl(gb, hvcc, sps_max_sub_layers_minus1);
++
++ get_ue_golomb_long(gb); // sps_seq_parameter_set_id
++
++ hvcc->chromaFormat = get_ue_golomb_long(gb);
++
++ if (hvcc->chromaFormat == 3)
++ skip_bits1(gb); // separate_colour_plane_flag
++
++ get_ue_golomb_long(gb); // pic_width_in_luma_samples
++ get_ue_golomb_long(gb); // pic_height_in_luma_samples
++
++ if (get_bits1(gb)) { // conformance_window_flag
++ get_ue_golomb_long(gb); // conf_win_left_offset
++ get_ue_golomb_long(gb); // conf_win_right_offset
++ get_ue_golomb_long(gb); // conf_win_top_offset
++ get_ue_golomb_long(gb); // conf_win_bottom_offset
++ }
++
++ hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb);
++ hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb);
++ log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb);
++
++ /* sps_sub_layer_ordering_info_present_flag */
++ i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1;
++ for (; i <= sps_max_sub_layers_minus1; i++)
++ skip_sub_layer_ordering_info(gb);
++
++ get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3
++ get_ue_golomb_long(gb); // log2_diff_max_min_luma_coding_block_size
++ get_ue_golomb_long(gb); // log2_min_transform_block_size_minus2
++ get_ue_golomb_long(gb); // log2_diff_max_min_transform_block_size
++ get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter
++ get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra
++
++ if (get_bits1(gb) && // scaling_list_enabled_flag
++ get_bits1(gb)) // sps_scaling_list_data_present_flag
++ skip_scaling_list_data(gb);
++
++ skip_bits1(gb); // amp_enabled_flag
++ skip_bits1(gb); // sample_adaptive_offset_enabled_flag
++
++ if (get_bits1(gb)) { // pcm_enabled_flag
++ skip_bits (gb, 4); // pcm_sample_bit_depth_luma_minus1
++ skip_bits (gb, 4); // pcm_sample_bit_depth_chroma_minus1
++ get_ue_golomb_long(gb); // log2_min_pcm_luma_coding_block_size_minus3
++ get_ue_golomb_long(gb); // log2_diff_max_min_pcm_luma_coding_block_size
++ skip_bits1 (gb); // pcm_loop_filter_disabled_flag
++ }
++
++ num_short_term_ref_pic_sets = get_ue_golomb_long(gb);
++ if (num_short_term_ref_pic_sets > MAX_SHORT_TERM_RPS_COUNT)
++ return AVERROR_INVALIDDATA;
++
++ for (i = 0; i < num_short_term_ref_pic_sets; i++) {
++ int ret = parse_rps(gb, i, num_short_term_ref_pic_sets, num_delta_pocs);
++ if (ret < 0)
++ return ret;
++ }
++
++ if (get_bits1(gb)) { // long_term_ref_pics_present_flag
++ for (i = 0; i < get_ue_golomb_long(gb); i++) { // num_long_term_ref_pics_sps
++ int len = FFMIN(log2_max_pic_order_cnt_lsb_minus4 + 4, 16);
++ skip_bits (gb, len); // lt_ref_pic_poc_lsb_sps[i]
++ skip_bits1(gb); // used_by_curr_pic_lt_sps_flag[i]
++ }
++ }
++
++ skip_bits1(gb); // sps_temporal_mvp_enabled_flag
++ skip_bits1(gb); // strong_intra_smoothing_enabled_flag
++
++ if (get_bits1(gb)) // vui_parameters_present_flag
++ hvcc_parse_vui(gb, hvcc, sps_max_sub_layers_minus1);
++
++ /* nothing useful for hvcC past this point */
++ return 0;
++}
++
++static int hvcc_parse_pps(GetBitContext *gb,
++ HEVCDecoderConfigurationRecord *hvcc)
++{
++ uint8_t tiles_enabled_flag, entropy_coding_sync_enabled_flag;
++
++ get_ue_golomb_long(gb); // pps_pic_parameter_set_id
++ get_ue_golomb_long(gb); // pps_seq_parameter_set_id
++
++ /*
++ * dependent_slice_segments_enabled_flag u(1)
++ * output_flag_present_flag u(1)
++ * num_extra_slice_header_bits u(3)
++ * sign_data_hiding_enabled_flag u(1)
++ * cabac_init_present_flag u(1)
++ */
++ skip_bits(gb, 7);
++
++ get_ue_golomb_long(gb); // num_ref_idx_l0_default_active_minus1
++ get_ue_golomb_long(gb); // num_ref_idx_l1_default_active_minus1
++ get_se_golomb_long(gb); // init_qp_minus26
++
++ /*
++ * constrained_intra_pred_flag u(1)
++ * transform_skip_enabled_flag u(1)
++ */
++ skip_bits(gb, 2);
++
++ if (get_bits1(gb)) // cu_qp_delta_enabled_flag
++ get_ue_golomb_long(gb); // diff_cu_qp_delta_depth
++
++ get_se_golomb_long(gb); // pps_cb_qp_offset
++ get_se_golomb_long(gb); // pps_cr_qp_offset
++
++ /*
++ * weighted_pred_flag u(1)
++ * weighted_bipred_flag u(1)
++ * transquant_bypass_enabled_flag u(1)
++ */
++ skip_bits(gb, 3);
++
++ tiles_enabled_flag = get_bits1(gb);
++ entropy_coding_sync_enabled_flag = get_bits1(gb);
++
++ if (entropy_coding_sync_enabled_flag && tiles_enabled_flag)
++ hvcc->parallelismType = 0; // mixed-type parallel decoding
++ else if (entropy_coding_sync_enabled_flag)
++ hvcc->parallelismType = 3; // wavefront-based parallel decoding
++ else if (tiles_enabled_flag)
++ hvcc->parallelismType = 2; // tile-based parallel decoding
++ else
++ hvcc->parallelismType = 1; // slice-based parallel decoding
++
++ /* nothing useful for hvcC past this point */
++ return 0;
++}
++
++static uint8_t *nal_unit_extract_rbsp(const uint8_t *src, uint32_t src_len,
++ uint32_t *dst_len)
++{
++ uint8_t *dst;
++ uint32_t i, len;
++
++ dst = av_malloc(src_len);
++ if (!dst)
++ return NULL;
++
++ /* NAL unit header (2 bytes) */
++ i = len = 0;
++ while (i < 2 && i < src_len)
++ dst[len++] = src[i++];
++
++ while (i + 2 < src_len)
++ if (!src[i] && !src[i + 1] && src[i + 2] == 3) {
++ dst[len++] = src[i++];
++ dst[len++] = src[i++];
++ i++; // remove emulation_prevention_three_byte
++ } else
++ dst[len++] = src[i++];
++
++ while (i < src_len)
++ dst[len++] = src[i++];
++
++ *dst_len = len;
++ return dst;
++}
++
++
++
++static void nal_unit_parse_header(GetBitContext *gb, uint8_t *nal_type)
++{
++ skip_bits1(gb); // forbidden_zero_bit
++
++ *nal_type = get_bits(gb, 6);
++
++ /*
++ * nuh_layer_id u(6)
++ * nuh_temporal_id_plus1 u(3)
++ */
++ skip_bits(gb, 9);
++}
++
++static int hvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
++ uint8_t nal_type, int ps_array_completeness,
++ HEVCDecoderConfigurationRecord *hvcc)
++{
++ int ret;
++ uint8_t index;
++ uint16_t numNalus;
++ HVCCNALUnitArray *array;
++
++ for (index = 0; index < hvcc->numOfArrays; index++)
++ if (hvcc->array[index].NAL_unit_type == nal_type)
++ break;
++
++ if (index >= hvcc->numOfArrays) {
++ uint8_t i;
++
++ ret = av_reallocp_array(&hvcc->array, index + 1, sizeof(HVCCNALUnitArray));
++ if (ret < 0)
++ return ret;
++
++ for (i = hvcc->numOfArrays; i <= index; i++)
++ memset(&hvcc->array[i], 0, sizeof(HVCCNALUnitArray));
++ hvcc->numOfArrays = index + 1;
++ }
++
++ array = &hvcc->array[index];
++ numNalus = array->numNalus;
++
++ ret = av_reallocp_array(&array->nalUnit, numNalus + 1, sizeof(uint8_t*));
++ if (ret < 0)
++ return ret;
++
++ ret = av_reallocp_array(&array->nalUnitLength, numNalus + 1, sizeof(uint16_t));
++ if (ret < 0)
++ return ret;
++
++ array->nalUnit [numNalus] = nal_buf;
++ array->nalUnitLength[numNalus] = nal_size;
++ array->NAL_unit_type = nal_type;
++ array->numNalus++;
++
++ /*
++ * When the sample entry name is ‘hvc1’, the default and mandatory value of
++ * array_completeness is 1 for arrays of all types of parameter sets, and 0
++ * for all other arrays. When the sample entry name is ‘hev1’, the default
++ * value of array_completeness is 0 for all arrays.
++ */
++ if (nal_type == NAL_VPS || nal_type == NAL_SPS || nal_type == NAL_PPS)
++ array->array_completeness = ps_array_completeness;
++
++ return 0;
++}
++
++static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size,
++ int ps_array_completeness,
++ HEVCDecoderConfigurationRecord *hvcc)
++{
++ int ret = 0;
++ GetBitContext gbc;
++ uint8_t nal_type;
++ uint8_t *rbsp_buf;
++ uint32_t rbsp_size;
++
++ rbsp_buf = nal_unit_extract_rbsp(nal_buf, nal_size, &rbsp_size);
++ if (!rbsp_buf) {
++ ret = AVERROR(ENOMEM);
++ goto end;
++ }
++
++ ret = init_get_bits8(&gbc, rbsp_buf, rbsp_size);
++ if (ret < 0)
++ goto end;
++
++ nal_unit_parse_header(&gbc, &nal_type);
++
++ /*
++ * Note: only 'declarative' SEI messages are allowed in
++ * hvcC. Perhaps the SEI playload type should be checked
++ * and non-declarative SEI messages discarded?
++ */
++ switch (nal_type) {
++ case NAL_VPS:
++ case NAL_SPS:
++ case NAL_PPS:
++ case NAL_SEI_PREFIX:
++ case NAL_SEI_SUFFIX:
++ ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type,
++ ps_array_completeness, hvcc);
++ if (ret < 0)
++ goto end;
++ else if (nal_type == NAL_VPS)
++ ret = hvcc_parse_vps(&gbc, hvcc);
++ else if (nal_type == NAL_SPS)
++ ret = hvcc_parse_sps(&gbc, hvcc);
++ else if (nal_type == NAL_PPS)
++ ret = hvcc_parse_pps(&gbc, hvcc);
++ if (ret < 0)
++ goto end;
++ break;
++ default:
++ ret = AVERROR_INVALIDDATA;
++ goto end;
++ }
++
++end:
++ av_free(rbsp_buf);
++ return ret;
++}
++
++static void hvcc_init(HEVCDecoderConfigurationRecord *hvcc)
++{
++ memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord));
++ hvcc->configurationVersion = 1;
++ hvcc->lengthSizeMinusOne = 3; // 4 bytes
++
++ /*
++ * The following fields have all their valid bits set by default,
++ * the ProfileTierLevel parsing code will unset them when needed.
++ */
++ hvcc->general_profile_compatibility_flags = 0xffffffff;
++ hvcc->general_constraint_indicator_flags = 0xffffffffffff;
++
++ /*
++ * Initialize this field with an invalid value which can be used to detect
++ * whether we didn't see any VUI (in wich case it should be reset to zero).
++ */
++ hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1;
++}
++
++static void hvcc_close(HEVCDecoderConfigurationRecord *hvcc)
++{
++ uint8_t i;
++
++ for (i = 0; i < hvcc->numOfArrays; i++) {
++ hvcc->array[i].numNalus = 0;
++ av_freep(&hvcc->array[i].nalUnit);
++ av_freep(&hvcc->array[i].nalUnitLength);
++ }
++
++ hvcc->numOfArrays = 0;
++ av_freep(&hvcc->array);
++}
++
++static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
++{
++ uint8_t i;
++ uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0;
++
++ /*
++ * We only support writing HEVCDecoderConfigurationRecord version 1.
++ */
++ hvcc->configurationVersion = 1;
++
++ /*
++ * If min_spatial_segmentation_idc is invalid, reset to 0 (unspecified).
++ */
++ if (hvcc->min_spatial_segmentation_idc > MAX_SPATIAL_SEGMENTATION)
++ hvcc->min_spatial_segmentation_idc = 0;
++
++ /*
++ * parallelismType indicates the type of parallelism that is used to meet
++ * the restrictions imposed by min_spatial_segmentation_idc when the value
++ * of min_spatial_segmentation_idc is greater than 0.
++ */
++ if (!hvcc->min_spatial_segmentation_idc)
++ hvcc->parallelismType = 0;
++
++ /*
++ * It's unclear how to properly compute these fields, so
++ * let's always set them to values meaning 'unspecified'.
++ */
++ hvcc->avgFrameRate = 0;
++ hvcc->constantFrameRate = 0;
++
++ av_dlog(NULL, "configurationVersion: %"PRIu8"\n",
++ hvcc->configurationVersion);
++ av_dlog(NULL, "general_profile_space: %"PRIu8"\n",
++ hvcc->general_profile_space);
++ av_dlog(NULL, "general_tier_flag: %"PRIu8"\n",
++ hvcc->general_tier_flag);
++ av_dlog(NULL, "general_profile_idc: %"PRIu8"\n",
++ hvcc->general_profile_idc);
++ av_dlog(NULL, "general_profile_compatibility_flags: 0x%08"PRIx32"\n",
++ hvcc->general_profile_compatibility_flags);
++ av_dlog(NULL, "general_constraint_indicator_flags: 0x%012"PRIx64"\n",
++ hvcc->general_constraint_indicator_flags);
++ av_dlog(NULL, "general_level_idc: %"PRIu8"\n",
++ hvcc->general_level_idc);
++ av_dlog(NULL, "min_spatial_segmentation_idc: %"PRIu16"\n",
++ hvcc->min_spatial_segmentation_idc);
++ av_dlog(NULL, "parallelismType: %"PRIu8"\n",
++ hvcc->parallelismType);
++ av_dlog(NULL, "chromaFormat: %"PRIu8"\n",
++ hvcc->chromaFormat);
++ av_dlog(NULL, "bitDepthLumaMinus8: %"PRIu8"\n",
++ hvcc->bitDepthLumaMinus8);
++ av_dlog(NULL, "bitDepthChromaMinus8: %"PRIu8"\n",
++ hvcc->bitDepthChromaMinus8);
++ av_dlog(NULL, "avgFrameRate: %"PRIu16"\n",
++ hvcc->avgFrameRate);
++ av_dlog(NULL, "constantFrameRate: %"PRIu8"\n",
++ hvcc->constantFrameRate);
++ av_dlog(NULL, "numTemporalLayers: %"PRIu8"\n",
++ hvcc->numTemporalLayers);
++ av_dlog(NULL, "temporalIdNested: %"PRIu8"\n",
++ hvcc->temporalIdNested);
++ av_dlog(NULL, "lengthSizeMinusOne: %"PRIu8"\n",
++ hvcc->lengthSizeMinusOne);
++ av_dlog(NULL, "numOfArrays: %"PRIu8"\n",
++ hvcc->numOfArrays);
++ for (i = 0; i < hvcc->numOfArrays; i++) {
++ av_dlog(NULL, "array_completeness[%"PRIu8"]: %"PRIu8"\n",
++ i, hvcc->array[i].array_completeness);
++ av_dlog(NULL, "NAL_unit_type[%"PRIu8"]: %"PRIu8"\n",
++ i, hvcc->array[i].NAL_unit_type);
++ av_dlog(NULL, "numNalus[%"PRIu8"]: %"PRIu16"\n",
++ i, hvcc->array[i].numNalus);
++ for (j = 0; j < hvcc->array[i].numNalus; j++)
++ av_dlog(NULL,
++ "nalUnitLength[%"PRIu8"][%"PRIu16"]: %"PRIu16"\n",
++ i, j, hvcc->array[i].nalUnitLength[j]);
++ }
++
++ /*
++ * We need at least one of each: VPS, SPS and PPS.
++ */
++ for (i = 0; i < hvcc->numOfArrays; i++)
++ switch (hvcc->array[i].NAL_unit_type) {
++ case NAL_VPS:
++ vps_count += hvcc->array[i].numNalus;
++ break;
++ case NAL_SPS:
++ sps_count += hvcc->array[i].numNalus;
++ break;
++ case NAL_PPS:
++ pps_count += hvcc->array[i].numNalus;
++ break;
++ default:
++ break;
++ }
++ if (!vps_count || vps_count > MAX_VPS_COUNT ||
++ !sps_count || sps_count > MAX_SPS_COUNT ||
++ !pps_count || pps_count > MAX_PPS_COUNT)
++ return AVERROR_INVALIDDATA;
++
++ /* unsigned int(8) configurationVersion = 1; */
++ avio_w8(pb, hvcc->configurationVersion);
++
++ /*
++ * unsigned int(2) general_profile_space;
++ * unsigned int(1) general_tier_flag;
++ * unsigned int(5) general_profile_idc;
++ */
++ avio_w8(pb, hvcc->general_profile_space << 6 |
++ hvcc->general_tier_flag << 5 |
++ hvcc->general_profile_idc);
++
++ /* unsigned int(32) general_profile_compatibility_flags; */
++ avio_wb32(pb, hvcc->general_profile_compatibility_flags);
++
++ /* unsigned int(48) general_constraint_indicator_flags; */
++ avio_wb32(pb, hvcc->general_constraint_indicator_flags >> 16);
++ avio_wb16(pb, hvcc->general_constraint_indicator_flags);
++
++ /* unsigned int(8) general_level_idc; */
++ avio_w8(pb, hvcc->general_level_idc);
++
++ /*
++ * bit(4) reserved = ‘1111’b;
++ * unsigned int(12) min_spatial_segmentation_idc;
++ */
++ avio_wb16(pb, hvcc->min_spatial_segmentation_idc | 0xf000);
++
++ /*
++ * bit(6) reserved = ‘111111’b;
++ * unsigned int(2) parallelismType;
++ */
++ avio_w8(pb, hvcc->parallelismType | 0xfc);
++
++ /*
++ * bit(6) reserved = ‘111111’b;
++ * unsigned int(2) chromaFormat;
++ */
++ avio_w8(pb, hvcc->chromaFormat | 0xfc);
++
++ /*
++ * bit(5) reserved = ‘11111’b;
++ * unsigned int(3) bitDepthLumaMinus8;
++ */
++ avio_w8(pb, hvcc->bitDepthLumaMinus8 | 0xf8);
++
++ /*
++ * bit(5) reserved = ‘11111’b;
++ * unsigned int(3) bitDepthChromaMinus8;
++ */
++ avio_w8(pb, hvcc->bitDepthChromaMinus8 | 0xf8);
++
++ /* bit(16) avgFrameRate; */
++ avio_wb16(pb, hvcc->avgFrameRate);
++
++ /*
++ * bit(2) constantFrameRate;
++ * bit(3) numTemporalLayers;
++ * bit(1) temporalIdNested;
++ * unsigned int(2) lengthSizeMinusOne;
++ */
++ avio_w8(pb, hvcc->constantFrameRate << 6 |
++ hvcc->numTemporalLayers << 3 |
++ hvcc->temporalIdNested << 2 |
++ hvcc->lengthSizeMinusOne);
++
++ /* unsigned int(8) numOfArrays; */
++ avio_w8(pb, hvcc->numOfArrays);
++
++ for (i = 0; i < hvcc->numOfArrays; i++) {
++ /*
++ * bit(1) array_completeness;
++ * unsigned int(1) reserved = 0;
++ * unsigned int(6) NAL_unit_type;
++ */
++ avio_w8(pb, hvcc->array[i].array_completeness << 7 |
++ hvcc->array[i].NAL_unit_type & 0x3f);
++
++ /* unsigned int(16) numNalus; */
++ avio_wb16(pb, hvcc->array[i].numNalus);
++
++ for (j = 0; j < hvcc->array[i].numNalus; j++) {
++ /* unsigned int(16) nalUnitLength; */
++ avio_wb16(pb, hvcc->array[i].nalUnitLength[j]);
++
++ /* bit(8*nalUnitLength) nalUnit; */
++ avio_write(pb, hvcc->array[i].nalUnit[j],
++ hvcc->array[i].nalUnitLength[j]);
++ }
++ }
++
++ return 0;
++}
++
++int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in,
++ int size, int filter_ps, int *ps_count)
++{
++ int num_ps = 0, ret = 0;
++ uint8_t *buf, *end, *start = NULL;
++
++ if (!filter_ps) {
++ ret = ff_avc_parse_nal_units(pb, buf_in, size);
++ goto end;
++ }
++
++ ret = ff_avc_parse_nal_units_buf(buf_in, &start, &size);
++ if (ret < 0)
++ goto end;
++
++ ret = 0;
++ buf = start;
++ end = start + size;
++
++ while (end - buf > 4) {
++ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
++ uint8_t type = (buf[4] >> 1) & 0x3f;
++
++ buf += 4;
++
++ switch (type) {
++ case NAL_VPS:
++ case NAL_SPS:
++ case NAL_PPS:
++ num_ps++;
++ break;
++ default:
++ ret += 4 + len;
++ avio_wb32(pb, len);
++ avio_write(pb, buf, len);
++ break;
++ }
++
++ buf += len;
++ }
++
++end:
++ av_free(start);
++ if (ps_count)
++ *ps_count = num_ps;
++ return ret;
++}
++
++int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out,
++ int *size, int filter_ps, int *ps_count)
++{
++ AVIOContext *pb;
++ int ret;
++
++ ret = avio_open_dyn_buf(&pb);
++ if (ret < 0)
++ return ret;
++
++ ret = ff_hevc_annexb2mp4(pb, buf_in, *size, filter_ps, ps_count);
++ *size = avio_close_dyn_buf(pb, buf_out);
++
++ return ret;
++}
++
++int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
++ int size, int ps_array_completeness)
++{
++ int ret = 0;
++ uint8_t *buf, *end, *start = NULL;
++ HEVCDecoderConfigurationRecord hvcc;
++
++ hvcc_init(&hvcc);
++
++ if (size < 6) {
++ /* We can't write a valid hvcC from the provided data */
++ ret = AVERROR_INVALIDDATA;
++ goto end;
++ } else if (*data == 1) {
++ /* Data is already hvcC-formatted */
++ avio_write(pb, data, size);
++ goto end;
++ } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) {
++ /* Not a valid Annex B start code prefix */
++ ret = AVERROR_INVALIDDATA;
++ goto end;
++ }
++
++ ret = ff_avc_parse_nal_units_buf(data, &start, &size);
++ if (ret < 0)
++ goto end;
++
++ buf = start;
++ end = start + size;
++
++ while (end - buf > 4) {
++ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
++ uint8_t type = (buf[4] >> 1) & 0x3f;
++
++ buf += 4;
++
++ switch (type) {
++ case NAL_VPS:
++ case NAL_SPS:
++ case NAL_PPS:
++ case NAL_SEI_PREFIX:
++ case NAL_SEI_SUFFIX:
++ ret = hvcc_add_nal_unit(buf, len, ps_array_completeness, &hvcc);
++ if (ret < 0)
++ goto end;
++ break;
++ default:
++ break;
++ }
++
++ buf += len;
++ }
++
++ ret = hvcc_write(pb, &hvcc);
++
++end:
++ hvcc_close(&hvcc);
++ av_free(start);
++ return ret;
++}
+diff --git a/libavformat/hevc.h b/libavformat/hevc.h
+new file mode 100644
+index 0000000..03c43bd
+--- /dev/null
++++ b/libavformat/hevc.h
+@@ -0,0 +1,98 @@
++/*
++ * Copyright (c) 2014 Tim Walker <[email protected]>
++ *
++ * This file is part of Libav.
++ *
++ * Libav 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 2.1 of the License, or (at your option) any later version.
++ *
++ * Libav 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 Libav; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++/**
++ * @file
++ * internal header for HEVC (de)muxer utilities
++ */
++
++#ifndef AVFORMAT_HEVC_H
++#define AVFORMAT_HEVC_H
++
++#include <stdint.h>
++#include "avio.h"
++
++/**
++ * Writes Annex B formatted HEVC NAL units to the provided AVIOContext.
++ *
++ * The NAL units are converted to an MP4-compatible format (start code prefixes
++ * are replaced by 4-byte size fields, as per ISO/IEC 14496-15).
++ *
++ * If filter_ps is non-zero, any HEVC parameter sets found in the input will be
++ * discarded, and *ps_count will be set to the number of discarded PS NAL units.
++ *
++ * @param pb address of the AVIOContext where the data shall be written
++ * @param buf_in address of the buffer holding the input data
++ * @param size size (in bytes) of the input buffer
++ * @param filter_ps whether to write parameter set NAL units to the output (0)
++ * or to discard them (non-zero)
++ * @param ps_count address of the variable where the number of discarded
++ * parameter set NAL units shall be written, may be NULL
++ * @return the amount (in bytes) of data written in case of success, a negative
++ * value corresponding to an AVERROR code in case of failure
++ */
++int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in,
++ int size, int filter_ps, int *ps_count);
++
++/**
++ * Writes Annex B formatted HEVC NAL units to a data buffer.
++ *
++ * The NAL units are converted to an MP4-compatible format (start code prefixes
++ * are replaced by 4-byte size fields, as per ISO/IEC 14496-15).
++ *
++ * If filter_ps is non-zero, any HEVC parameter sets found in the input will be
++ * discarded, and *ps_count will be set to the number of discarded PS NAL units.
++ *
++ * On output, *size holds the size (in bytes) of the output data buffer.
++ *
++ * @param buf_in address of the buffer holding the input data
++ * @param size address of the variable holding the size (in bytes) of the input
++ * buffer (on input) and of the output buffer (on output)
++ * @param buf_out address of the variable holding the address of the output
++ * buffer
++ * @param filter_ps whether to write parameter set NAL units to the output (0)
++ * or to discard them (non-zero)
++ * @param ps_count address of the variable where the number of discarded
++ * parameter set NAL units shall be written, may be NULL
++ * @return the amount (in bytes) of data written in case of success, a negative
++ * value corresponding to an AVERROR code in case of failure
++ */
++int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out,
++ int *size, int filter_ps, int *ps_count);
++
++/**
++ * Writes HEVC extradata (parameter sets, declarative SEI NAL units) to the
++ * provided AVIOContext.
++ *
++ * If the extradata is Annex B format, it gets converted to hvcC format before
++ * writing.
++ *
++ * @param pb address of the AVIOContext where the hvcC shall be written
++ * @param data address of the buffer holding the data needed to write the hvcC
++ * @param size size (in bytes) of the data buffer
++ * @param ps_array_completeness whether all parameter sets are in the hvcC (1)
++ * or there may be additional parameter sets in the bitstream (0)
++ * @return 0 in case of success, a negative value corresponding to an AVERROR
++ * code in case of failure
++ */
++int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
++ int size, int ps_array_completeness);
++
++#endif /* AVFORMAT_HEVC_H */
+diff --git a/libavformat/isom.c b/libavformat/isom.c
+index 9b32b7d..76c455b 100644
+--- a/libavformat/isom.c
++++ b/libavformat/isom.c
+@@ -33,6 +33,7 @@ const AVCodecTag ff_mp4_obj_type[] = {
+ { AV_CODEC_ID_MOV_TEXT , 0x08 },
+ { AV_CODEC_ID_MPEG4 , 0x20 },
+ { AV_CODEC_ID_H264 , 0x21 },
++ { AV_CODEC_ID_HEVC , 0x23 },
+ { AV_CODEC_ID_AAC , 0x40 },
+ { AV_CODEC_ID_MP4ALS , 0x40 }, /* 14496-3 ALS */
+ { AV_CODEC_ID_MPEG2VIDEO , 0x61 }, /* MPEG2 Main */
+@@ -136,8 +137,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
+
+ { AV_CODEC_ID_RAWVIDEO, MKTAG('W', 'R', 'A', 'W') },
+
+- { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, /* HEVC/H.265 which indicates parameter sets shall not be in ES */
+ { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, /* HEVC/H.265 which indicates parameter sets may be in ES */
++ { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, /* HEVC/H.265 which indicates parameter sets shall not be in ES */
+
+ { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '1') }, /* AVC-1/H.264 */
+ { AV_CODEC_ID_H264, MKTAG('a', 'i', '5', 'p') }, /* AVC-Intra 50M 720p24/30/60 */
+diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
+index cc645a5..08f5552 100644
+--- a/libavformat/matroskaenc.c
++++ b/libavformat/matroskaenc.c
+@@ -22,6 +22,7 @@
+ #include <stdint.h>
+
+ #include "avc.h"
++#include "hevc.h"
+ #include "avformat.h"
+ #include "avlanguage.h"
+ #include "flacenc.h"
+@@ -500,6 +501,8 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
+ ret = put_wv_codecpriv(dyn_cp, codec);
+ else if (codec->codec_id == AV_CODEC_ID_H264)
+ ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size);
++ else if (codec->codec_id == AV_CODEC_ID_HEVC)
++ ret = ff_isom_write_hvcc(dyn_cp, codec->extradata, codec->extradata_size, 0);
+ else if (codec->codec_id == AV_CODEC_ID_ALAC) {
+ if (codec->extradata_size < 36) {
+ av_log(s, AV_LOG_ERROR,
+@@ -1160,6 +1163,10 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
+ if (codec->codec_id == AV_CODEC_ID_H264 && codec->extradata_size > 0 &&
+ (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1))
+ ff_avc_parse_nal_units_buf(pkt->data, &data, &size);
++ else if (codec->codec_id == AV_CODEC_ID_HEVC && codec->extradata_size > 6 &&
++ (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1))
++ /* extradata is Annex B, assume the bitstream is too and convert it */
++ ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL);
+ else if (codec->codec_id == AV_CODEC_ID_WAVPACK) {
+ int ret = mkv_strip_wavpack(pkt->data, &data, &size);
+ if (ret < 0) {
+diff --git a/libavformat/movenc.c b/libavformat/movenc.c
+index 43a1647..415d808 100644
+--- a/libavformat/movenc.c
++++ b/libavformat/movenc.c
+@@ -39,6 +39,7 @@
+ #include "libavutil/mathematics.h"
+ #include "libavutil/opt.h"
+ #include "libavutil/dict.h"
++#include "hevc.h"
+ #include "rtpenc.h"
+ #include "mov_chan.h"
+
+@@ -685,6 +686,16 @@ static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
+ return update_size(pb, pos);
+ }
+
++static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
++{
++ int64_t pos = avio_tell(pb);
++
++ avio_wb32(pb, 0);
++ ffio_wfourcc(pb, "hvcC");
++ ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
++ return update_size(pb, pos);
++}
++
+ /* also used by all avid codecs (dv, imx, meridien) and their variants */
+ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
+ {
+@@ -741,6 +752,7 @@ static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
+ return 0;
+
+ if (track->enc->codec_id == AV_CODEC_ID_H264) tag = MKTAG('a','v','c','1');
++ else if (track->enc->codec_id == AV_CODEC_ID_HEVC) tag = MKTAG('h','e','v','1');
+ else if (track->enc->codec_id == AV_CODEC_ID_AC3) tag = MKTAG('a','c','-','3');
+ else if (track->enc->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c');
+ else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g');
+@@ -1035,6 +1047,8 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track)
+ mov_write_svq3_tag(pb);
+ else if (track->enc->codec_id == AV_CODEC_ID_DNXHD)
+ mov_write_avid_tag(pb, track);
++ else if (track->enc->codec_id == AV_CODEC_ID_HEVC)
++ mov_write_hvcc_tag(pb, track);
+ else if (track->enc->codec_id == AV_CODEC_ID_H264) {
+ mov_write_avcc_tag(pb, track);
+ if (track->mode == MODE_IPOD)
+@@ -2925,6 +2939,15 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
+ } else {
+ size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
+ }
++ } else if (enc->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
++ (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
++ /* extradata is Annex B, assume the bitstream is too and convert it */
++ if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
++ ff_hevc_annexb2mp4_buf(pkt->data, &reformatted_data, &size, 0, NULL);
++ avio_write(pb, reformatted_data, size);
++ } else {
++ size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
++ }
+ } else {
+ avio_write(pb, pkt->data, size);
+ }
diff --git a/libhb/common.c b/libhb/common.c
index 34bc5a047..8f206c69f 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -57,7 +57,6 @@ enum
HB_GID_ACODEC_VORBIS,
HB_GID_MUX_MKV,
HB_GID_MUX_MP4,
- HB_GID_MUX_265,
};
typedef struct
@@ -207,7 +206,7 @@ hb_encoder_internal_t hb_video_encoders[] =
// actual encoders
{ { "H.264 (x264)", "x264", "H.264 (libx264)", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, },
{ { "H.264 (Intel QSV)", "qsv_h264", "H.264 (Intel Media SDK)", HB_VCODEC_QSV_H264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, },
- { { "H.265 (x265)", "x265", "H.265 (libx265)", HB_VCODEC_X265, HB_MUX_X265, }, NULL, 1, HB_GID_VCODEC_H265, },
+ { { "H.265 (x265)", "x265", "H.265 (libx265)", HB_VCODEC_X265, HB_MUX_AV_MP4|HB_MUX_AV_MKV, }, NULL, 1, HB_GID_VCODEC_H265, },
{ { "MPEG-4", "mpeg4", "MPEG-4 (libavcodec)", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG4, },
{ { "MPEG-2", "mpeg2", "MPEG-2 (libavcodec)", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG2, },
{ { "Theora", "theora", "Theora (libtheora)", HB_VCODEC_THEORA, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_THEORA, },
@@ -331,7 +330,6 @@ hb_container_internal_t hb_containers[] =
{ { "MPEG-4 (mp4v2)", "mp4v2", "MPEG-4 (libmp4v2)", "mp4", HB_MUX_MP4V2, }, NULL, 1, HB_GID_MUX_MP4, },
{ { "Matroska (avformat)", "av_mkv", "Matroska (libavformat)", "mkv", HB_MUX_AV_MKV, }, NULL, 1, HB_GID_MUX_MKV, },
{ { "Matroska (libmkv)", "libmkv", "Matroska (libmkv)", "mkv", HB_MUX_LIBMKV, }, NULL, 1, HB_GID_MUX_MKV, },
- { { "Raw H.265 (x265)", "x265", "H.265 (raw stream)", "265", HB_MUX_X265, }, NULL, 1, HB_GID_MUX_265, },
};
int hb_containers_count = sizeof(hb_containers) / sizeof(hb_containers[0]);
static int hb_container_is_enabled(int format)
@@ -348,9 +346,6 @@ static int hb_container_is_enabled(int format)
case HB_MUX_AV_MP4:
case HB_MUX_AV_MKV:
#endif
-#ifdef USE_X265
- case HB_MUX_X265:
-#endif
return 1;
default:
diff --git a/libhb/common.h b/libhb/common.h
index bc790e2d9..4ccac8402 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -515,7 +515,6 @@ struct hb_job_s
#define HB_MUX_AV_MKV 0x200000
#define HB_MUX_MASK_MKV 0x300000
#define HB_MUX_MASK_AV 0x220000
-#define HB_MUX_X265 0x000001
/* default muxer for each container */
#define HB_MUX_MP4 HB_MUX_AV_MP4
#define HB_MUX_MKV HB_MUX_AV_MKV
diff --git a/libhb/encx265.c b/libhb/encx265.c
index 610d06128..7ed280371 100644
--- a/libhb/encx265.c
+++ b/libhb/encx265.c
@@ -54,8 +54,6 @@ struct hb_work_private_s
}
frame_info[FRAME_INFO_SIZE];
- FILE *fout;
-
char csvfn[1024];
};
@@ -82,18 +80,6 @@ int encx265Init(hb_work_object_t *w, hb_job_t *job)
x265_nal *nal;
uint32_t nnal;
- if (job->mux == HB_MUX_X265)
- {
- pv->fout = fopen(job->file, "wb");
- if (pv->fout == NULL || fseek(pv->fout, 0L, SEEK_SET) < 0)
- {
- hb_error("encx265: fopen failed.");
- free(pv);
- pv = NULL;
- return 1;
- }
- }
-
x265_param *param = pv->param = x265_param_alloc();
if (x265_param_default_preset(param,
@@ -222,15 +208,6 @@ int encx265Init(hb_work_object_t *w, hb_job_t *job)
return 1;
}
- if (job->mux == HB_MUX_X265)
- {
- for (i = 0; i < nnal; i++)
- {
- fwrite(nal[i].payload, 1, nal[i].sizeBytes, pv->fout);
- }
- return 0;
- }
-
/*
* x265's output (headers and bitstream) are in Annex B format.
*
@@ -274,7 +251,6 @@ void encx265Close(hb_work_object_t *w)
x265_param_free(pv->param);
x265_encoder_close(pv->x265);
- fclose(pv->fout);
free(pv);
w->private_data = NULL;
}
@@ -380,16 +356,6 @@ static hb_buffer_t* nal_encode(hb_work_object_t *w,
}
}
- if (job->mux == HB_MUX_X265)
- {
- for (i = 0; i < nnal; i++)
- {
- fwrite(nal[i].payload, 1, nal[i].sizeBytes, pv->fout);
- }
- hb_buffer_close(&buf);
- return NULL;
- }
-
// discard empty buffers (no video)
if (buf->size <= 0)
{
diff --git a/libhb/muxcommon.c b/libhb/muxcommon.c
index fa412cbca..4738bfa2a 100644
--- a/libhb/muxcommon.c
+++ b/libhb/muxcommon.c
@@ -475,10 +475,6 @@ hb_work_object_t * hb_muxer_init( hb_job_t * job )
mux->m = hb_mux_avformat_init( job );
break;
#endif
-#ifdef USE_X265
- case HB_MUX_X265:
- break;
-#endif
default:
hb_error( "No muxer selected, exiting" );
*job->done_error = HB_ERROR_INIT;