/src/vlc/contrib/contrib-build/bpg/libavcodec/hevc_sei.c
Line | Count | Source |
1 | | /* |
2 | | * HEVC Supplementary Enhancement Information messages |
3 | | * |
4 | | * Copyright (C) 2012 - 2013 Guillaume Martres |
5 | | * Copyright (C) 2012 - 2013 Gildas Cocherel |
6 | | * Copyright (C) 2013 Vittorio Giovara |
7 | | * |
8 | | * This file is part of FFmpeg. |
9 | | * |
10 | | * FFmpeg is free software; you can redistribute it and/or |
11 | | * modify it under the terms of the GNU Lesser General Public |
12 | | * License as published by the Free Software Foundation; either |
13 | | * version 2.1 of the License, or (at your option) any later version. |
14 | | * |
15 | | * FFmpeg is distributed in the hope that it will be useful, |
16 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 | | * Lesser General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU Lesser General Public |
21 | | * License along with FFmpeg; if not, write to the Free Software |
22 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
23 | | */ |
24 | | |
25 | | #include "golomb.h" |
26 | | #include "hevc.h" |
27 | | |
28 | | static void decode_nal_sei_decoded_picture_hash(HEVCContext *s) |
29 | 0 | { |
30 | 0 | int cIdx, i; |
31 | 0 | uint8_t hash_type; |
32 | | //uint16_t picture_crc; |
33 | | //uint32_t picture_checksum; |
34 | 0 | GetBitContext *gb = &s->HEVClc->gb; |
35 | 0 | hash_type = get_bits(gb, 8); |
36 | |
|
37 | 0 | for (cIdx = 0; cIdx < 3/*((s->sps->chroma_format_idc == 0) ? 1 : 3)*/; cIdx++) { |
38 | 0 | if (hash_type == 0) { |
39 | 0 | s->is_md5 = 1; |
40 | 0 | for (i = 0; i < 16; i++) |
41 | 0 | s->md5[cIdx][i] = get_bits(gb, 8); |
42 | 0 | } else if (hash_type == 1) { |
43 | | // picture_crc = get_bits(gb, 16); |
44 | 0 | skip_bits(gb, 16); |
45 | 0 | } else if (hash_type == 2) { |
46 | | // picture_checksum = get_bits_long(gb, 32); |
47 | 0 | skip_bits(gb, 32); |
48 | 0 | } |
49 | 0 | } |
50 | 0 | } |
51 | | |
52 | | #ifdef USE_FULL |
53 | | static void decode_nal_sei_frame_packing_arrangement(HEVCContext *s) |
54 | | { |
55 | | GetBitContext *gb = &s->HEVClc->gb; |
56 | | |
57 | | get_ue_golomb(gb); // frame_packing_arrangement_id |
58 | | s->sei_frame_packing_present = !get_bits1(gb); |
59 | | |
60 | | if (s->sei_frame_packing_present) { |
61 | | s->frame_packing_arrangement_type = get_bits(gb, 7); |
62 | | s->quincunx_subsampling = get_bits1(gb); |
63 | | s->content_interpretation_type = get_bits(gb, 6); |
64 | | |
65 | | // the following skips spatial_flipping_flag frame0_flipped_flag |
66 | | // field_views_flag current_frame_is_frame0_flag |
67 | | // frame0_self_contained_flag frame1_self_contained_flag |
68 | | skip_bits(gb, 6); |
69 | | |
70 | | if (!s->quincunx_subsampling && s->frame_packing_arrangement_type != 5) |
71 | | skip_bits(gb, 16); // frame[01]_grid_position_[xy] |
72 | | skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte |
73 | | skip_bits1(gb); // frame_packing_arrangement_persistance_flag |
74 | | } |
75 | | skip_bits1(gb); // upsampled_aspect_ratio_flag |
76 | | } |
77 | | |
78 | | static void decode_nal_sei_display_orientation(HEVCContext *s) |
79 | | { |
80 | | GetBitContext *gb = &s->HEVClc->gb; |
81 | | |
82 | | s->sei_display_orientation_present = !get_bits1(gb); |
83 | | |
84 | | if (s->sei_display_orientation_present) { |
85 | | s->sei_hflip = get_bits1(gb); // hor_flip |
86 | | s->sei_vflip = get_bits1(gb); // ver_flip |
87 | | |
88 | | s->sei_anticlockwise_rotation = get_bits(gb, 16); |
89 | | skip_bits1(gb); // display_orientation_persistence_flag |
90 | | } |
91 | | } |
92 | | |
93 | | static int decode_pic_timing(HEVCContext *s) |
94 | | { |
95 | | GetBitContext *gb = &s->HEVClc->gb; |
96 | | HEVCSPS *sps; |
97 | | |
98 | | if (!s->sps_list[s->active_seq_parameter_set_id]) |
99 | | return(AVERROR(ENOMEM)); |
100 | | sps = (HEVCSPS*)s->sps_list[s->active_seq_parameter_set_id]->data; |
101 | | |
102 | | if (sps->vui.frame_field_info_present_flag) { |
103 | | int pic_struct = get_bits(gb, 4); |
104 | | s->picture_struct = AV_PICTURE_STRUCTURE_UNKNOWN; |
105 | | if (pic_struct == 2) { |
106 | | av_log(s->avctx, AV_LOG_DEBUG, "BOTTOM Field\n"); |
107 | | s->picture_struct = AV_PICTURE_STRUCTURE_BOTTOM_FIELD; |
108 | | } else if (pic_struct == 1) { |
109 | | av_log(s->avctx, AV_LOG_DEBUG, "TOP Field\n"); |
110 | | s->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD; |
111 | | } |
112 | | get_bits(gb, 2); // source_scan_type |
113 | | get_bits(gb, 1); // duplicate_flag |
114 | | } |
115 | | return 1; |
116 | | } |
117 | | |
118 | | static int active_parameter_sets(HEVCContext *s) |
119 | | { |
120 | | GetBitContext *gb = &s->HEVClc->gb; |
121 | | int num_sps_ids_minus1; |
122 | | int i; |
123 | | unsigned active_seq_parameter_set_id; |
124 | | |
125 | | get_bits(gb, 4); // active_video_parameter_set_id |
126 | | get_bits(gb, 1); // self_contained_cvs_flag |
127 | | get_bits(gb, 1); // num_sps_ids_minus1 |
128 | | num_sps_ids_minus1 = get_ue_golomb_long(gb); // num_sps_ids_minus1 |
129 | | |
130 | | active_seq_parameter_set_id = get_ue_golomb_long(gb); |
131 | | if (active_seq_parameter_set_id >= MAX_SPS_COUNT) { |
132 | | av_log(s->avctx, AV_LOG_ERROR, "active_parameter_set_id %d invalid\n", active_seq_parameter_set_id); |
133 | | return AVERROR_INVALIDDATA; |
134 | | } |
135 | | s->active_seq_parameter_set_id = active_seq_parameter_set_id; |
136 | | |
137 | | for (i = 1; i <= num_sps_ids_minus1; i++) |
138 | | get_ue_golomb_long(gb); // active_seq_parameter_set_id[i] |
139 | | |
140 | | return 0; |
141 | | } |
142 | | #endif |
143 | | |
144 | | static int decode_nal_sei_message(HEVCContext *s) |
145 | 0 | { |
146 | 0 | GetBitContext *gb = &s->HEVClc->gb; |
147 | |
|
148 | 0 | int payload_type = 0; |
149 | 0 | int payload_size = 0; |
150 | 0 | int byte = 0xFF; |
151 | 0 | av_log(s->avctx, AV_LOG_DEBUG, "Decoding SEI\n"); |
152 | |
|
153 | 0 | while (byte == 0xFF) { |
154 | 0 | byte = get_bits(gb, 8); |
155 | 0 | payload_type += byte; |
156 | 0 | } |
157 | 0 | byte = 0xFF; |
158 | 0 | while (byte == 0xFF) { |
159 | 0 | byte = get_bits(gb, 8); |
160 | 0 | payload_size += byte; |
161 | 0 | } |
162 | 0 | if (s->nal_unit_type == NAL_SEI_PREFIX) { |
163 | 0 | if (payload_type == 256 /*&& s->decode_checksum_sei*/) { |
164 | 0 | decode_nal_sei_decoded_picture_hash(s); |
165 | 0 | } else |
166 | | #ifdef USE_FULL |
167 | | if (payload_type == 45) { |
168 | | decode_nal_sei_frame_packing_arrangement(s); |
169 | | } else if (payload_type == 47) { |
170 | | decode_nal_sei_display_orientation(s); |
171 | | } else if (payload_type == 1){ |
172 | | int ret = decode_pic_timing(s); |
173 | | av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); |
174 | | skip_bits(gb, 8 * payload_size); |
175 | | return ret; |
176 | | } else if (payload_type == 129){ |
177 | | active_parameter_sets(s); |
178 | | av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); |
179 | | } else |
180 | | #endif |
181 | 0 | #ifdef USE_FRAME_DURATION_SEI |
182 | 0 | if (payload_type == 257) { |
183 | | /* frame duration in multiples of the frame rate period */ |
184 | 0 | s->frame_duration = get_bits(gb, 16); |
185 | 0 | } else |
186 | 0 | #endif |
187 | 0 | { |
188 | 0 | av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); |
189 | 0 | skip_bits(gb, 8*payload_size); |
190 | 0 | } |
191 | 0 | } else { /* nal_unit_type == NAL_SEI_SUFFIX */ |
192 | 0 | if (payload_type == 132 /* && s->decode_checksum_sei */) |
193 | 0 | decode_nal_sei_decoded_picture_hash(s); |
194 | 0 | else { |
195 | 0 | av_log(s->avctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", payload_type); |
196 | 0 | skip_bits(gb, 8 * payload_size); |
197 | 0 | } |
198 | 0 | } |
199 | 0 | return 1; |
200 | 0 | } |
201 | | |
202 | | static int more_rbsp_data(GetBitContext *gb) |
203 | 0 | { |
204 | 0 | return get_bits_left(gb) > 0 && show_bits(gb, 8) != 0x80; |
205 | 0 | } |
206 | | |
207 | | int ff_hevc_decode_nal_sei(HEVCContext *s) |
208 | 0 | { |
209 | 0 | int ret; |
210 | |
|
211 | 0 | do { |
212 | 0 | ret = decode_nal_sei_message(s); |
213 | 0 | if (ret < 0) |
214 | 0 | return(AVERROR(ENOMEM)); |
215 | 0 | } while (more_rbsp_data(&s->HEVClc->gb)); |
216 | 0 | return 1; |
217 | 0 | } |