1/*
2Copyright (c) 2011 Stanislav Vitvitskiy
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of this
5software and associated documentation files (the "Software"), to deal in the Software
6without restriction, including without limitation the rights to use, copy, modify,
7merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
8permit persons to whom the Software is furnished to do so, subject to the following
9conditions:
10
11The above copyright notice and this permission notice shall be included in all copies or
12substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
19OR OTHER DEALINGS IN THE SOFTWARE.
20*/
21package com.googlecode.mp4parser.h264.model;
22
23import com.googlecode.mp4parser.h264.read.CAVLCReader;
24import com.googlecode.mp4parser.h264.write.CAVLCWriter;
25
26import java.io.IOException;
27import java.io.InputStream;
28import java.io.OutputStream;
29
30/**
31 * Sequence Parameter Set structure of h264 bitstream
32 * <p/>
33 * capable to serialize and deserialize with CAVLC bitstream
34 *
35 * @author Stanislav Vitvitskiy
36 */
37public class SeqParameterSet extends BitstreamElement {
38    public int pic_order_cnt_type;
39    public boolean field_pic_flag;
40    public boolean delta_pic_order_always_zero_flag;
41    public boolean weighted_pred_flag;
42    public int weighted_bipred_idc;
43    public boolean entropy_coding_mode_flag;
44    public boolean mb_adaptive_frame_field_flag;
45    public boolean direct_8x8_inference_flag;
46    public ChromaFormat chroma_format_idc;
47    public int log2_max_frame_num_minus4;
48    public int log2_max_pic_order_cnt_lsb_minus4;
49    public int pic_height_in_map_units_minus1;
50    public int pic_width_in_mbs_minus1;
51    public int bit_depth_luma_minus8;
52    public int bit_depth_chroma_minus8;
53    public boolean qpprime_y_zero_transform_bypass_flag;
54    public int profile_idc;
55    public boolean constraint_set_0_flag;
56    public boolean constraint_set_1_flag;
57    public boolean constraint_set_2_flag;
58    public boolean constraint_set_3_flag;
59    public int level_idc;
60    public int seq_parameter_set_id;
61    public boolean residual_color_transform_flag;
62    public int offset_for_non_ref_pic;
63    public int offset_for_top_to_bottom_field;
64    public int num_ref_frames;
65    public boolean gaps_in_frame_num_value_allowed_flag;
66    public boolean frame_mbs_only_flag;
67    public boolean frame_cropping_flag;
68    public int frame_crop_left_offset;
69    public int frame_crop_right_offset;
70    public int frame_crop_top_offset;
71    public int frame_crop_bottom_offset;
72    public int[] offsetForRefFrame;
73    public VUIParameters vuiParams;
74    public ScalingMatrix scalingMatrix;
75    public int num_ref_frames_in_pic_order_cnt_cycle;
76
77    public static SeqParameterSet read(InputStream is) throws IOException {
78        CAVLCReader reader = new CAVLCReader(is);
79        SeqParameterSet sps = new SeqParameterSet();
80
81        sps.profile_idc = (int) reader.readNBit(8, "SPS: profile_idc");
82        sps.constraint_set_0_flag = reader
83                .readBool("SPS: constraint_set_0_flag");
84        sps.constraint_set_1_flag = reader
85                .readBool("SPS: constraint_set_1_flag");
86        sps.constraint_set_2_flag = reader
87                .readBool("SPS: constraint_set_2_flag");
88        sps.constraint_set_3_flag = reader
89                .readBool("SPS: constraint_set_3_flag");
90        reader.readNBit(4, "SPS: reserved_zero_4bits");
91        sps.level_idc = (int) reader.readNBit(8, "SPS: level_idc");
92        sps.seq_parameter_set_id = reader.readUE("SPS: seq_parameter_set_id");
93
94        if (sps.profile_idc == 100 || sps.profile_idc == 110
95                || sps.profile_idc == 122 || sps.profile_idc == 144) {
96            sps.chroma_format_idc = ChromaFormat.fromId(reader
97                    .readUE("SPS: chroma_format_idc"));
98            if (sps.chroma_format_idc == ChromaFormat.YUV_444) {
99                sps.residual_color_transform_flag = reader
100                        .readBool("SPS: residual_color_transform_flag");
101            }
102            sps.bit_depth_luma_minus8 = reader
103                    .readUE("SPS: bit_depth_luma_minus8");
104            sps.bit_depth_chroma_minus8 = reader
105                    .readUE("SPS: bit_depth_chroma_minus8");
106            sps.qpprime_y_zero_transform_bypass_flag = reader
107                    .readBool("SPS: qpprime_y_zero_transform_bypass_flag");
108            boolean seqScalingMatrixPresent = reader
109                    .readBool("SPS: seq_scaling_matrix_present_lag");
110            if (seqScalingMatrixPresent) {
111                readScalingListMatrix(reader, sps);
112            }
113        } else {
114            sps.chroma_format_idc = ChromaFormat.YUV_420;
115        }
116        sps.log2_max_frame_num_minus4 = reader
117                .readUE("SPS: log2_max_frame_num_minus4");
118        sps.pic_order_cnt_type = reader.readUE("SPS: pic_order_cnt_type");
119        if (sps.pic_order_cnt_type == 0) {
120            sps.log2_max_pic_order_cnt_lsb_minus4 = reader
121                    .readUE("SPS: log2_max_pic_order_cnt_lsb_minus4");
122        } else if (sps.pic_order_cnt_type == 1) {
123            sps.delta_pic_order_always_zero_flag = reader
124                    .readBool("SPS: delta_pic_order_always_zero_flag");
125            sps.offset_for_non_ref_pic = reader
126                    .readSE("SPS: offset_for_non_ref_pic");
127            sps.offset_for_top_to_bottom_field = reader
128                    .readSE("SPS: offset_for_top_to_bottom_field");
129            sps.num_ref_frames_in_pic_order_cnt_cycle = reader
130                    .readUE("SPS: num_ref_frames_in_pic_order_cnt_cycle");
131            sps.offsetForRefFrame = new int[sps.num_ref_frames_in_pic_order_cnt_cycle];
132            for (int i = 0; i < sps.num_ref_frames_in_pic_order_cnt_cycle; i++) {
133                sps.offsetForRefFrame[i] = reader
134                        .readSE("SPS: offsetForRefFrame [" + i + "]");
135            }
136        }
137        sps.num_ref_frames = reader.readUE("SPS: num_ref_frames");
138        sps.gaps_in_frame_num_value_allowed_flag = reader
139                .readBool("SPS: gaps_in_frame_num_value_allowed_flag");
140        sps.pic_width_in_mbs_minus1 = reader
141                .readUE("SPS: pic_width_in_mbs_minus1");
142        sps.pic_height_in_map_units_minus1 = reader
143                .readUE("SPS: pic_height_in_map_units_minus1");
144        sps.frame_mbs_only_flag = reader.readBool("SPS: frame_mbs_only_flag");
145        if (!sps.frame_mbs_only_flag) {
146            sps.mb_adaptive_frame_field_flag = reader
147                    .readBool("SPS: mb_adaptive_frame_field_flag");
148        }
149        sps.direct_8x8_inference_flag = reader
150                .readBool("SPS: direct_8x8_inference_flag");
151        sps.frame_cropping_flag = reader.readBool("SPS: frame_cropping_flag");
152        if (sps.frame_cropping_flag) {
153            sps.frame_crop_left_offset = reader
154                    .readUE("SPS: frame_crop_left_offset");
155            sps.frame_crop_right_offset = reader
156                    .readUE("SPS: frame_crop_right_offset");
157            sps.frame_crop_top_offset = reader
158                    .readUE("SPS: frame_crop_top_offset");
159            sps.frame_crop_bottom_offset = reader
160                    .readUE("SPS: frame_crop_bottom_offset");
161        }
162        boolean vui_parameters_present_flag = reader
163                .readBool("SPS: vui_parameters_present_flag");
164        if (vui_parameters_present_flag)
165            sps.vuiParams = ReadVUIParameters(reader);
166
167        reader.readTrailingBits();
168
169        return sps;
170    }
171
172    private static void readScalingListMatrix(CAVLCReader reader,
173                                              SeqParameterSet sps) throws IOException {
174        sps.scalingMatrix = new ScalingMatrix();
175        for (int i = 0; i < 8; i++) {
176            boolean seqScalingListPresentFlag = reader
177                    .readBool("SPS: seqScalingListPresentFlag");
178            if (seqScalingListPresentFlag) {
179                sps.scalingMatrix.ScalingList4x4 = new ScalingList[8];
180                sps.scalingMatrix.ScalingList8x8 = new ScalingList[8];
181                if (i < 6) {
182                    sps.scalingMatrix.ScalingList4x4[i] = ScalingList.read(
183                            reader, 16);
184                } else {
185                    sps.scalingMatrix.ScalingList8x8[i - 6] = ScalingList.read(
186                            reader, 64);
187                }
188            }
189        }
190    }
191
192    private static VUIParameters ReadVUIParameters(CAVLCReader reader)
193            throws IOException {
194        VUIParameters vuip = new VUIParameters();
195        vuip.aspect_ratio_info_present_flag = reader
196                .readBool("VUI: aspect_ratio_info_present_flag");
197        if (vuip.aspect_ratio_info_present_flag) {
198            vuip.aspect_ratio = AspectRatio.fromValue((int) reader.readNBit(8,
199                    "VUI: aspect_ratio"));
200            if (vuip.aspect_ratio == AspectRatio.Extended_SAR) {
201                vuip.sar_width = (int) reader.readNBit(16, "VUI: sar_width");
202                vuip.sar_height = (int) reader.readNBit(16, "VUI: sar_height");
203            }
204        }
205        vuip.overscan_info_present_flag = reader
206                .readBool("VUI: overscan_info_present_flag");
207        if (vuip.overscan_info_present_flag) {
208            vuip.overscan_appropriate_flag = reader
209                    .readBool("VUI: overscan_appropriate_flag");
210        }
211        vuip.video_signal_type_present_flag = reader
212                .readBool("VUI: video_signal_type_present_flag");
213        if (vuip.video_signal_type_present_flag) {
214            vuip.video_format = (int) reader.readNBit(3, "VUI: video_format");
215            vuip.video_full_range_flag = reader
216                    .readBool("VUI: video_full_range_flag");
217            vuip.colour_description_present_flag = reader
218                    .readBool("VUI: colour_description_present_flag");
219            if (vuip.colour_description_present_flag) {
220                vuip.colour_primaries = (int) reader.readNBit(8,
221                        "VUI: colour_primaries");
222                vuip.transfer_characteristics = (int) reader.readNBit(8,
223                        "VUI: transfer_characteristics");
224                vuip.matrix_coefficients = (int) reader.readNBit(8,
225                        "VUI: matrix_coefficients");
226            }
227        }
228        vuip.chroma_loc_info_present_flag = reader
229                .readBool("VUI: chroma_loc_info_present_flag");
230        if (vuip.chroma_loc_info_present_flag) {
231            vuip.chroma_sample_loc_type_top_field = reader
232                    .readUE("VUI chroma_sample_loc_type_top_field");
233            vuip.chroma_sample_loc_type_bottom_field = reader
234                    .readUE("VUI chroma_sample_loc_type_bottom_field");
235        }
236        vuip.timing_info_present_flag = reader
237                .readBool("VUI: timing_info_present_flag");
238        if (vuip.timing_info_present_flag) {
239            vuip.num_units_in_tick = (int) reader.readNBit(32,
240                    "VUI: num_units_in_tick");
241            vuip.time_scale = (int) reader.readNBit(32, "VUI: time_scale");
242            vuip.fixed_frame_rate_flag = reader
243                    .readBool("VUI: fixed_frame_rate_flag");
244        }
245        boolean nal_hrd_parameters_present_flag = reader
246                .readBool("VUI: nal_hrd_parameters_present_flag");
247        if (nal_hrd_parameters_present_flag)
248            vuip.nalHRDParams = readHRDParameters(reader);
249        boolean vcl_hrd_parameters_present_flag = reader
250                .readBool("VUI: vcl_hrd_parameters_present_flag");
251        if (vcl_hrd_parameters_present_flag)
252            vuip.vclHRDParams = readHRDParameters(reader);
253        if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
254            vuip.low_delay_hrd_flag = reader
255                    .readBool("VUI: low_delay_hrd_flag");
256        }
257        vuip.pic_struct_present_flag = reader
258                .readBool("VUI: pic_struct_present_flag");
259        boolean bitstream_restriction_flag = reader
260                .readBool("VUI: bitstream_restriction_flag");
261        if (bitstream_restriction_flag) {
262            vuip.bitstreamRestriction = new VUIParameters.BitstreamRestriction();
263            vuip.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = reader
264                    .readBool("VUI: motion_vectors_over_pic_boundaries_flag");
265            vuip.bitstreamRestriction.max_bytes_per_pic_denom = reader
266                    .readUE("VUI max_bytes_per_pic_denom");
267            vuip.bitstreamRestriction.max_bits_per_mb_denom = reader
268                    .readUE("VUI max_bits_per_mb_denom");
269            vuip.bitstreamRestriction.log2_max_mv_length_horizontal = reader
270                    .readUE("VUI log2_max_mv_length_horizontal");
271            vuip.bitstreamRestriction.log2_max_mv_length_vertical = reader
272                    .readUE("VUI log2_max_mv_length_vertical");
273            vuip.bitstreamRestriction.num_reorder_frames = reader
274                    .readUE("VUI num_reorder_frames");
275            vuip.bitstreamRestriction.max_dec_frame_buffering = reader
276                    .readUE("VUI max_dec_frame_buffering");
277        }
278
279        return vuip;
280    }
281
282    private static HRDParameters readHRDParameters(CAVLCReader reader)
283            throws IOException {
284        HRDParameters hrd = new HRDParameters();
285        hrd.cpb_cnt_minus1 = reader.readUE("SPS: cpb_cnt_minus1");
286        hrd.bit_rate_scale = (int) reader.readNBit(4, "HRD: bit_rate_scale");
287        hrd.cpb_size_scale = (int) reader.readNBit(4, "HRD: cpb_size_scale");
288        hrd.bit_rate_value_minus1 = new int[hrd.cpb_cnt_minus1 + 1];
289        hrd.cpb_size_value_minus1 = new int[hrd.cpb_cnt_minus1 + 1];
290        hrd.cbr_flag = new boolean[hrd.cpb_cnt_minus1 + 1];
291
292        for (int SchedSelIdx = 0; SchedSelIdx <= hrd.cpb_cnt_minus1; SchedSelIdx++) {
293            hrd.bit_rate_value_minus1[SchedSelIdx] = reader
294                    .readUE("HRD: bit_rate_value_minus1");
295            hrd.cpb_size_value_minus1[SchedSelIdx] = reader
296                    .readUE("HRD: cpb_size_value_minus1");
297            hrd.cbr_flag[SchedSelIdx] = reader.readBool("HRD: cbr_flag");
298        }
299        hrd.initial_cpb_removal_delay_length_minus1 = (int) reader.readNBit(5,
300                "HRD: initial_cpb_removal_delay_length_minus1");
301        hrd.cpb_removal_delay_length_minus1 = (int) reader.readNBit(5,
302                "HRD: cpb_removal_delay_length_minus1");
303        hrd.dpb_output_delay_length_minus1 = (int) reader.readNBit(5,
304                "HRD: dpb_output_delay_length_minus1");
305        hrd.time_offset_length = (int) reader.readNBit(5,
306                "HRD: time_offset_length");
307        return hrd;
308    }
309
310    public void write(OutputStream out) throws IOException {
311        CAVLCWriter writer = new CAVLCWriter(out);
312
313        writer.writeNBit(profile_idc, 8, "SPS: profile_idc");
314        writer.writeBool(constraint_set_0_flag, "SPS: constraint_set_0_flag");
315        writer.writeBool(constraint_set_1_flag, "SPS: constraint_set_1_flag");
316        writer.writeBool(constraint_set_2_flag, "SPS: constraint_set_2_flag");
317        writer.writeBool(constraint_set_3_flag, "SPS: constraint_set_3_flag");
318        writer.writeNBit(0, 4, "SPS: reserved");
319        writer.writeNBit(level_idc, 8, "SPS: level_idc");
320        writer.writeUE(seq_parameter_set_id, "SPS: seq_parameter_set_id");
321
322        if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122
323                || profile_idc == 144) {
324            writer.writeUE(chroma_format_idc.getId(), "SPS: chroma_format_idc");
325            if (chroma_format_idc == ChromaFormat.YUV_444) {
326                writer.writeBool(residual_color_transform_flag,
327                        "SPS: residual_color_transform_flag");
328            }
329            writer.writeUE(bit_depth_luma_minus8, "SPS: ");
330            writer.writeUE(bit_depth_chroma_minus8, "SPS: ");
331            writer.writeBool(qpprime_y_zero_transform_bypass_flag,
332                    "SPS: qpprime_y_zero_transform_bypass_flag");
333            writer.writeBool(scalingMatrix != null, "SPS: ");
334            if (scalingMatrix != null) {
335                for (int i = 0; i < 8; i++) {
336                    if (i < 6) {
337                        writer.writeBool(
338                                scalingMatrix.ScalingList4x4[i] != null,
339                                "SPS: ");
340                        if (scalingMatrix.ScalingList4x4[i] != null) {
341                            scalingMatrix.ScalingList4x4[i].write(writer);
342                        }
343                    } else {
344                        writer.writeBool(
345                                scalingMatrix.ScalingList8x8[i - 6] != null,
346                                "SPS: ");
347                        if (scalingMatrix.ScalingList8x8[i - 6] != null) {
348                            scalingMatrix.ScalingList8x8[i - 6].write(writer);
349                        }
350                    }
351                }
352            }
353        }
354        writer.writeUE(log2_max_frame_num_minus4,
355                "SPS: log2_max_frame_num_minus4");
356        writer.writeUE(pic_order_cnt_type, "SPS: pic_order_cnt_type");
357        if (pic_order_cnt_type == 0) {
358            writer.writeUE(log2_max_pic_order_cnt_lsb_minus4,
359                    "SPS: log2_max_pic_order_cnt_lsb_minus4");
360        } else if (pic_order_cnt_type == 1) {
361            writer.writeBool(delta_pic_order_always_zero_flag,
362                    "SPS: delta_pic_order_always_zero_flag");
363            writer.writeSE(offset_for_non_ref_pic,
364                    "SPS: offset_for_non_ref_pic");
365            writer.writeSE(offset_for_top_to_bottom_field,
366                    "SPS: offset_for_top_to_bottom_field");
367            writer.writeUE(offsetForRefFrame.length, "SPS: ");
368            for (int i = 0; i < offsetForRefFrame.length; i++)
369                writer.writeSE(offsetForRefFrame[i], "SPS: ");
370        }
371        writer.writeUE(num_ref_frames, "SPS: num_ref_frames");
372        writer.writeBool(gaps_in_frame_num_value_allowed_flag,
373                "SPS: gaps_in_frame_num_value_allowed_flag");
374        writer.writeUE(pic_width_in_mbs_minus1, "SPS: pic_width_in_mbs_minus1");
375        writer.writeUE(pic_height_in_map_units_minus1,
376                "SPS: pic_height_in_map_units_minus1");
377        writer.writeBool(frame_mbs_only_flag, "SPS: frame_mbs_only_flag");
378        if (!frame_mbs_only_flag) {
379            writer.writeBool(mb_adaptive_frame_field_flag,
380                    "SPS: mb_adaptive_frame_field_flag");
381        }
382        writer.writeBool(direct_8x8_inference_flag,
383                "SPS: direct_8x8_inference_flag");
384        writer.writeBool(frame_cropping_flag, "SPS: frame_cropping_flag");
385        if (frame_cropping_flag) {
386            writer.writeUE(frame_crop_left_offset,
387                    "SPS: frame_crop_left_offset");
388            writer.writeUE(frame_crop_right_offset,
389                    "SPS: frame_crop_right_offset");
390            writer.writeUE(frame_crop_top_offset, "SPS: frame_crop_top_offset");
391            writer.writeUE(frame_crop_bottom_offset,
392                    "SPS: frame_crop_bottom_offset");
393        }
394        writer.writeBool(vuiParams != null, "SPS: ");
395        if (vuiParams != null)
396            writeVUIParameters(vuiParams, writer);
397
398        writer.writeTrailingBits();
399    }
400
401    private void writeVUIParameters(VUIParameters vuip, CAVLCWriter writer)
402            throws IOException {
403        writer.writeBool(vuip.aspect_ratio_info_present_flag,
404                "VUI: aspect_ratio_info_present_flag");
405        if (vuip.aspect_ratio_info_present_flag) {
406            writer.writeNBit(vuip.aspect_ratio.getValue(), 8,
407                    "VUI: aspect_ratio");
408            if (vuip.aspect_ratio == AspectRatio.Extended_SAR) {
409                writer.writeNBit(vuip.sar_width, 16, "VUI: sar_width");
410                writer.writeNBit(vuip.sar_height, 16, "VUI: sar_height");
411            }
412        }
413        writer.writeBool(vuip.overscan_info_present_flag,
414                "VUI: overscan_info_present_flag");
415        if (vuip.overscan_info_present_flag) {
416            writer.writeBool(vuip.overscan_appropriate_flag,
417                    "VUI: overscan_appropriate_flag");
418        }
419        writer.writeBool(vuip.video_signal_type_present_flag,
420                "VUI: video_signal_type_present_flag");
421        if (vuip.video_signal_type_present_flag) {
422            writer.writeNBit(vuip.video_format, 3, "VUI: video_format");
423            writer.writeBool(vuip.video_full_range_flag,
424                    "VUI: video_full_range_flag");
425            writer.writeBool(vuip.colour_description_present_flag,
426                    "VUI: colour_description_present_flag");
427            if (vuip.colour_description_present_flag) {
428                writer.writeNBit(vuip.colour_primaries, 8,
429                        "VUI: colour_primaries");
430                writer.writeNBit(vuip.transfer_characteristics, 8,
431                        "VUI: transfer_characteristics");
432                writer.writeNBit(vuip.matrix_coefficients, 8,
433                        "VUI: matrix_coefficients");
434            }
435        }
436        writer.writeBool(vuip.chroma_loc_info_present_flag,
437                "VUI: chroma_loc_info_present_flag");
438        if (vuip.chroma_loc_info_present_flag) {
439            writer.writeUE(vuip.chroma_sample_loc_type_top_field,
440                    "VUI: chroma_sample_loc_type_top_field");
441            writer.writeUE(vuip.chroma_sample_loc_type_bottom_field,
442                    "VUI: chroma_sample_loc_type_bottom_field");
443        }
444        writer.writeBool(vuip.timing_info_present_flag,
445                "VUI: timing_info_present_flag");
446        if (vuip.timing_info_present_flag) {
447            writer.writeNBit(vuip.num_units_in_tick, 32,
448                    "VUI: num_units_in_tick");
449            writer.writeNBit(vuip.time_scale, 32, "VUI: time_scale");
450            writer.writeBool(vuip.fixed_frame_rate_flag,
451                    "VUI: fixed_frame_rate_flag");
452        }
453        writer.writeBool(vuip.nalHRDParams != null, "VUI: ");
454        if (vuip.nalHRDParams != null) {
455            writeHRDParameters(vuip.nalHRDParams, writer);
456        }
457        writer.writeBool(vuip.vclHRDParams != null, "VUI: ");
458        if (vuip.vclHRDParams != null) {
459            writeHRDParameters(vuip.vclHRDParams, writer);
460        }
461
462        if (vuip.nalHRDParams != null || vuip.vclHRDParams != null) {
463            writer
464                    .writeBool(vuip.low_delay_hrd_flag,
465                            "VUI: low_delay_hrd_flag");
466        }
467        writer.writeBool(vuip.pic_struct_present_flag,
468                "VUI: pic_struct_present_flag");
469        writer.writeBool(vuip.bitstreamRestriction != null, "VUI: ");
470        if (vuip.bitstreamRestriction != null) {
471            writer
472                    .writeBool(
473                            vuip.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag,
474                            "VUI: motion_vectors_over_pic_boundaries_flag");
475            writer.writeUE(vuip.bitstreamRestriction.max_bytes_per_pic_denom,
476                    "VUI: max_bytes_per_pic_denom");
477            writer.writeUE(vuip.bitstreamRestriction.max_bits_per_mb_denom,
478                    "VUI: max_bits_per_mb_denom");
479            writer.writeUE(
480                    vuip.bitstreamRestriction.log2_max_mv_length_horizontal,
481                    "VUI: log2_max_mv_length_horizontal");
482            writer.writeUE(
483                    vuip.bitstreamRestriction.log2_max_mv_length_vertical,
484                    "VUI: log2_max_mv_length_vertical");
485            writer.writeUE(vuip.bitstreamRestriction.num_reorder_frames,
486                    "VUI: num_reorder_frames");
487            writer.writeUE(vuip.bitstreamRestriction.max_dec_frame_buffering,
488                    "VUI: max_dec_frame_buffering");
489        }
490
491    }
492
493    private void writeHRDParameters(HRDParameters hrd, CAVLCWriter writer)
494            throws IOException {
495        writer.writeUE(hrd.cpb_cnt_minus1, "HRD: cpb_cnt_minus1");
496        writer.writeNBit(hrd.bit_rate_scale, 4, "HRD: bit_rate_scale");
497        writer.writeNBit(hrd.cpb_size_scale, 4, "HRD: cpb_size_scale");
498
499        for (int SchedSelIdx = 0; SchedSelIdx <= hrd.cpb_cnt_minus1; SchedSelIdx++) {
500            writer.writeUE(hrd.bit_rate_value_minus1[SchedSelIdx], "HRD: ");
501            writer.writeUE(hrd.cpb_size_value_minus1[SchedSelIdx], "HRD: ");
502            writer.writeBool(hrd.cbr_flag[SchedSelIdx], "HRD: ");
503        }
504        writer.writeNBit(hrd.initial_cpb_removal_delay_length_minus1, 5,
505                "HRD: initial_cpb_removal_delay_length_minus1");
506        writer.writeNBit(hrd.cpb_removal_delay_length_minus1, 5,
507                "HRD: cpb_removal_delay_length_minus1");
508        writer.writeNBit(hrd.dpb_output_delay_length_minus1, 5,
509                "HRD: dpb_output_delay_length_minus1");
510        writer.writeNBit(hrd.time_offset_length, 5, "HRD: time_offset_length");
511    }
512
513    @Override
514    public String toString() {
515        return "SeqParameterSet{ " +
516                "\n        pic_order_cnt_type=" + pic_order_cnt_type +
517                ", \n        field_pic_flag=" + field_pic_flag +
518                ", \n        delta_pic_order_always_zero_flag=" + delta_pic_order_always_zero_flag +
519                ", \n        weighted_pred_flag=" + weighted_pred_flag +
520                ", \n        weighted_bipred_idc=" + weighted_bipred_idc +
521                ", \n        entropy_coding_mode_flag=" + entropy_coding_mode_flag +
522                ", \n        mb_adaptive_frame_field_flag=" + mb_adaptive_frame_field_flag +
523                ", \n        direct_8x8_inference_flag=" + direct_8x8_inference_flag +
524                ", \n        chroma_format_idc=" + chroma_format_idc +
525                ", \n        log2_max_frame_num_minus4=" + log2_max_frame_num_minus4 +
526                ", \n        log2_max_pic_order_cnt_lsb_minus4=" + log2_max_pic_order_cnt_lsb_minus4 +
527                ", \n        pic_height_in_map_units_minus1=" + pic_height_in_map_units_minus1 +
528                ", \n        pic_width_in_mbs_minus1=" + pic_width_in_mbs_minus1 +
529                ", \n        bit_depth_luma_minus8=" + bit_depth_luma_minus8 +
530                ", \n        bit_depth_chroma_minus8=" + bit_depth_chroma_minus8 +
531                ", \n        qpprime_y_zero_transform_bypass_flag=" + qpprime_y_zero_transform_bypass_flag +
532                ", \n        profile_idc=" + profile_idc +
533                ", \n        constraint_set_0_flag=" + constraint_set_0_flag +
534                ", \n        constraint_set_1_flag=" + constraint_set_1_flag +
535                ", \n        constraint_set_2_flag=" + constraint_set_2_flag +
536                ", \n        constraint_set_3_flag=" + constraint_set_3_flag +
537                ", \n        level_idc=" + level_idc +
538                ", \n        seq_parameter_set_id=" + seq_parameter_set_id +
539                ", \n        residual_color_transform_flag=" + residual_color_transform_flag +
540                ", \n        offset_for_non_ref_pic=" + offset_for_non_ref_pic +
541                ", \n        offset_for_top_to_bottom_field=" + offset_for_top_to_bottom_field +
542                ", \n        num_ref_frames=" + num_ref_frames +
543                ", \n        gaps_in_frame_num_value_allowed_flag=" + gaps_in_frame_num_value_allowed_flag +
544                ", \n        frame_mbs_only_flag=" + frame_mbs_only_flag +
545                ", \n        frame_cropping_flag=" + frame_cropping_flag +
546                ", \n        frame_crop_left_offset=" + frame_crop_left_offset +
547                ", \n        frame_crop_right_offset=" + frame_crop_right_offset +
548                ", \n        frame_crop_top_offset=" + frame_crop_top_offset +
549                ", \n        frame_crop_bottom_offset=" + frame_crop_bottom_offset +
550                ", \n        offsetForRefFrame=" + offsetForRefFrame +
551                ", \n        vuiParams=" + vuiParams +
552                ", \n        scalingMatrix=" + scalingMatrix +
553                ", \n        num_ref_frames_in_pic_order_cnt_cycle=" + num_ref_frames_in_pic_order_cnt_cycle +
554                '}';
555    }
556}