|
| 1 | +use crate::avc::FromCType; |
| 2 | +use crate::bindings::*; |
| 3 | +use crate::common::CType; |
| 4 | + |
| 5 | +pub const ZEROBYTES_SHORTSTARTCODE: i32 = 2; |
| 6 | +pub const AVC_CC_DATA_INITIAL_SIZE: usize = 1024; |
| 7 | +pub const MAXBFRAMES: i32 = 50; |
| 8 | + |
| 9 | +#[derive(Debug, Clone)] |
| 10 | +pub struct AvcContextRust { |
| 11 | + pub cc_count: u8, |
| 12 | + pub cc_data: Vec<u8>, |
| 13 | + pub cc_databufsize: usize, |
| 14 | + pub cc_buffer_saved: bool, |
| 15 | + |
| 16 | + pub got_seq_para: bool, |
| 17 | + pub nal_ref_idc: u32, |
| 18 | + pub seq_parameter_set_id: i64, |
| 19 | + pub log2_max_frame_num: i32, |
| 20 | + pub pic_order_cnt_type: i32, |
| 21 | + pub log2_max_pic_order_cnt_lsb: i32, |
| 22 | + pub frame_mbs_only_flag: bool, |
| 23 | + |
| 24 | + // Statistics for debugging |
| 25 | + pub num_nal_unit_type_7: i64, |
| 26 | + pub num_vcl_hrd: i64, |
| 27 | + pub num_nal_hrd: i64, |
| 28 | + pub num_jump_in_frames: i64, |
| 29 | + pub num_unexpected_sei_length: i64, |
| 30 | + |
| 31 | + pub ccblocks_in_avc_total: i32, |
| 32 | + pub ccblocks_in_avc_lost: i32, |
| 33 | + |
| 34 | + pub frame_num: i64, |
| 35 | + pub lastframe_num: i64, |
| 36 | + pub currref: i32, |
| 37 | + pub maxidx: i32, |
| 38 | + pub lastmaxidx: i32, |
| 39 | + |
| 40 | + // Used to find tref zero in PTS mode |
| 41 | + pub minidx: i32, |
| 42 | + pub lastminidx: i32, |
| 43 | + |
| 44 | + // Used to remember the max temporal reference number (poc mode) |
| 45 | + pub maxtref: i32, |
| 46 | + pub last_gop_maxtref: i32, |
| 47 | + |
| 48 | + // Used for PTS ordering of CC blocks |
| 49 | + pub currefpts: i64, |
| 50 | + pub last_pic_order_cnt_lsb: i64, |
| 51 | + pub last_slice_pts: i64, |
| 52 | +} |
| 53 | + |
| 54 | +impl Default for AvcContextRust { |
| 55 | + fn default() -> Self { |
| 56 | + AvcContextRust { |
| 57 | + cc_count: 0, |
| 58 | + cc_data: Vec::with_capacity(1024), |
| 59 | + cc_databufsize: 1024, |
| 60 | + cc_buffer_saved: true, |
| 61 | + |
| 62 | + got_seq_para: false, |
| 63 | + nal_ref_idc: 0, |
| 64 | + seq_parameter_set_id: 0, |
| 65 | + log2_max_frame_num: 0, |
| 66 | + pic_order_cnt_type: 0, |
| 67 | + log2_max_pic_order_cnt_lsb: 0, |
| 68 | + frame_mbs_only_flag: false, |
| 69 | + |
| 70 | + num_nal_unit_type_7: 0, |
| 71 | + num_vcl_hrd: 0, |
| 72 | + num_nal_hrd: 0, |
| 73 | + num_jump_in_frames: 0, |
| 74 | + num_unexpected_sei_length: 0, |
| 75 | + |
| 76 | + ccblocks_in_avc_total: 0, |
| 77 | + ccblocks_in_avc_lost: 0, |
| 78 | + |
| 79 | + frame_num: -1, |
| 80 | + lastframe_num: -1, |
| 81 | + currref: 0, |
| 82 | + maxidx: -1, |
| 83 | + lastmaxidx: -1, |
| 84 | + |
| 85 | + minidx: 10000, |
| 86 | + lastminidx: 10000, |
| 87 | + |
| 88 | + maxtref: 0, |
| 89 | + last_gop_maxtref: 0, |
| 90 | + |
| 91 | + currefpts: 0, |
| 92 | + last_pic_order_cnt_lsb: -1, |
| 93 | + last_slice_pts: -1, |
| 94 | + } |
| 95 | + } |
| 96 | +} |
| 97 | + |
| 98 | +impl FromCType<avc_ctx> for AvcContextRust { |
| 99 | + unsafe fn from_ctype(ctx: avc_ctx) -> Option<Self> { |
| 100 | + // Convert cc_data from C pointer to Vec |
| 101 | + let cc_data = if !ctx.cc_data.is_null() && ctx.cc_databufsize > 0 { |
| 102 | + std::slice::from_raw_parts(ctx.cc_data, ctx.cc_databufsize as usize).to_vec() |
| 103 | + } else { |
| 104 | + Vec::with_capacity(1024) |
| 105 | + }; |
| 106 | + |
| 107 | + Some(AvcContextRust { |
| 108 | + cc_count: ctx.cc_count, |
| 109 | + cc_data, |
| 110 | + cc_databufsize: ctx.cc_databufsize as usize, |
| 111 | + cc_buffer_saved: ctx.cc_buffer_saved != 0, |
| 112 | + |
| 113 | + got_seq_para: ctx.got_seq_para != 0, |
| 114 | + nal_ref_idc: ctx.nal_ref_idc, |
| 115 | + seq_parameter_set_id: ctx.seq_parameter_set_id, |
| 116 | + log2_max_frame_num: ctx.log2_max_frame_num, |
| 117 | + pic_order_cnt_type: ctx.pic_order_cnt_type, |
| 118 | + log2_max_pic_order_cnt_lsb: ctx.log2_max_pic_order_cnt_lsb, |
| 119 | + frame_mbs_only_flag: ctx.frame_mbs_only_flag != 0, |
| 120 | + |
| 121 | + num_nal_unit_type_7: ctx.num_nal_unit_type_7 as _, |
| 122 | + num_vcl_hrd: ctx.num_vcl_hrd as _, |
| 123 | + num_nal_hrd: ctx.num_nal_hrd as _, |
| 124 | + num_jump_in_frames: ctx.num_jump_in_frames as _, |
| 125 | + num_unexpected_sei_length: ctx.num_unexpected_sei_length as _, |
| 126 | + |
| 127 | + ccblocks_in_avc_total: ctx.ccblocks_in_avc_total, |
| 128 | + ccblocks_in_avc_lost: ctx.ccblocks_in_avc_lost, |
| 129 | + |
| 130 | + frame_num: ctx.frame_num, |
| 131 | + lastframe_num: ctx.lastframe_num, |
| 132 | + currref: ctx.currref, |
| 133 | + maxidx: ctx.maxidx, |
| 134 | + lastmaxidx: ctx.lastmaxidx, |
| 135 | + |
| 136 | + minidx: ctx.minidx, |
| 137 | + lastminidx: ctx.lastminidx, |
| 138 | + |
| 139 | + maxtref: ctx.maxtref, |
| 140 | + last_gop_maxtref: ctx.last_gop_maxtref, |
| 141 | + |
| 142 | + currefpts: ctx.currefpts, |
| 143 | + last_pic_order_cnt_lsb: ctx.last_pic_order_cnt_lsb, |
| 144 | + last_slice_pts: ctx.last_slice_pts, |
| 145 | + }) |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +impl CType<avc_ctx> for AvcContextRust { |
| 150 | + unsafe fn to_ctype(&self) -> avc_ctx { |
| 151 | + // Allocate cc_data buffer |
| 152 | + let cc_data_ptr = if !self.cc_data.is_empty() { |
| 153 | + let data_box = self.cc_data.clone().into_boxed_slice(); |
| 154 | + Box::into_raw(data_box) as *mut u8 |
| 155 | + } else { |
| 156 | + std::ptr::null_mut() |
| 157 | + }; |
| 158 | + |
| 159 | + avc_ctx { |
| 160 | + cc_count: self.cc_count, |
| 161 | + cc_data: cc_data_ptr, |
| 162 | + cc_databufsize: self.cc_databufsize as _, |
| 163 | + cc_buffer_saved: if self.cc_buffer_saved { 1 } else { 0 }, |
| 164 | + |
| 165 | + got_seq_para: if self.got_seq_para { 1 } else { 0 }, |
| 166 | + nal_ref_idc: self.nal_ref_idc, |
| 167 | + seq_parameter_set_id: self.seq_parameter_set_id, |
| 168 | + log2_max_frame_num: self.log2_max_frame_num, |
| 169 | + pic_order_cnt_type: self.pic_order_cnt_type, |
| 170 | + log2_max_pic_order_cnt_lsb: self.log2_max_pic_order_cnt_lsb, |
| 171 | + frame_mbs_only_flag: if self.frame_mbs_only_flag { 1 } else { 0 }, |
| 172 | + |
| 173 | + num_nal_unit_type_7: self.num_nal_unit_type_7 as _, |
| 174 | + num_vcl_hrd: self.num_vcl_hrd as _, |
| 175 | + num_nal_hrd: self.num_nal_hrd as _, |
| 176 | + num_jump_in_frames: self.num_jump_in_frames as _, |
| 177 | + num_unexpected_sei_length: self.num_unexpected_sei_length as _, |
| 178 | + |
| 179 | + ccblocks_in_avc_total: self.ccblocks_in_avc_total, |
| 180 | + ccblocks_in_avc_lost: self.ccblocks_in_avc_lost, |
| 181 | + |
| 182 | + frame_num: self.frame_num, |
| 183 | + lastframe_num: self.lastframe_num, |
| 184 | + currref: self.currref, |
| 185 | + maxidx: self.maxidx, |
| 186 | + lastmaxidx: self.lastmaxidx, |
| 187 | + |
| 188 | + minidx: self.minidx, |
| 189 | + lastminidx: self.lastminidx, |
| 190 | + |
| 191 | + maxtref: self.maxtref, |
| 192 | + last_gop_maxtref: self.last_gop_maxtref, |
| 193 | + |
| 194 | + currefpts: self.currefpts, |
| 195 | + last_pic_order_cnt_lsb: self.last_pic_order_cnt_lsb, |
| 196 | + last_slice_pts: self.last_slice_pts, |
| 197 | + } |
| 198 | + } |
| 199 | +} |
| 200 | + |
| 201 | +// SEI payload types |
| 202 | +#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 203 | +#[repr(u32)] |
| 204 | +pub enum SeiPayloadType { |
| 205 | + BufferingPeriod = 0, |
| 206 | + PicTiming = 1, |
| 207 | + PanScanRect = 2, |
| 208 | + FillerPayload = 3, |
| 209 | + UserDataRegisteredItuTT35 = 4, |
| 210 | + UserDataUnregistered = 5, |
| 211 | + RecoveryPoint = 6, |
| 212 | + DecRefPicMarkingRepetition = 7, |
| 213 | + SparePic = 8, |
| 214 | + SceneInfo = 9, |
| 215 | + SubSeqInfo = 10, |
| 216 | + SubSeqLayerCharacteristics = 11, |
| 217 | + SubSeqCharacteristics = 12, |
| 218 | + FullFrameFreeze = 13, |
| 219 | + FullFrameFreezeRelease = 14, |
| 220 | + FullFrameSnapshot = 15, |
| 221 | + ProgressiveRefinementSegmentStart = 16, |
| 222 | + ProgressiveRefinementSegmentEnd = 17, |
| 223 | + MotionConstrainedSliceGroupSet = 18, |
| 224 | + FilmGrainCharacteristics = 19, |
| 225 | + DeblockingFilterDisplayPreference = 20, |
| 226 | + StereoVideoInfo = 21, |
| 227 | +} |
| 228 | + |
| 229 | +impl From<u32> for SeiPayloadType { |
| 230 | + fn from(value: u32) -> Self { |
| 231 | + match value { |
| 232 | + 0 => SeiPayloadType::BufferingPeriod, |
| 233 | + 1 => SeiPayloadType::PicTiming, |
| 234 | + 2 => SeiPayloadType::PanScanRect, |
| 235 | + 3 => SeiPayloadType::FillerPayload, |
| 236 | + 4 => SeiPayloadType::UserDataRegisteredItuTT35, |
| 237 | + 5 => SeiPayloadType::UserDataUnregistered, |
| 238 | + 6 => SeiPayloadType::RecoveryPoint, |
| 239 | + 7 => SeiPayloadType::DecRefPicMarkingRepetition, |
| 240 | + 8 => SeiPayloadType::SparePic, |
| 241 | + 9 => SeiPayloadType::SceneInfo, |
| 242 | + 10 => SeiPayloadType::SubSeqInfo, |
| 243 | + 11 => SeiPayloadType::SubSeqLayerCharacteristics, |
| 244 | + 12 => SeiPayloadType::SubSeqCharacteristics, |
| 245 | + 13 => SeiPayloadType::FullFrameFreeze, |
| 246 | + 14 => SeiPayloadType::FullFrameFreezeRelease, |
| 247 | + 15 => SeiPayloadType::FullFrameSnapshot, |
| 248 | + 16 => SeiPayloadType::ProgressiveRefinementSegmentStart, |
| 249 | + 17 => SeiPayloadType::ProgressiveRefinementSegmentEnd, |
| 250 | + 18 => SeiPayloadType::MotionConstrainedSliceGroupSet, |
| 251 | + 19 => SeiPayloadType::FilmGrainCharacteristics, |
| 252 | + 20 => SeiPayloadType::DeblockingFilterDisplayPreference, |
| 253 | + 21 => SeiPayloadType::StereoVideoInfo, |
| 254 | + _ => SeiPayloadType::UserDataUnregistered, // Default fallback |
| 255 | + } |
| 256 | + } |
| 257 | +} |
| 258 | +// NAL unit types from H.264 standard |
| 259 | +#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 260 | +#[repr(u8)] |
| 261 | +pub enum NalUnitType { |
| 262 | + Unspecified = 0, |
| 263 | + CodedSliceNonIdr = 1, |
| 264 | + CodedSliceDataPartitionA = 2, |
| 265 | + CodedSliceDataPartitionB = 3, |
| 266 | + CodedSliceDataPartitionC = 4, |
| 267 | + CodedSliceIdr = 5, |
| 268 | + Sei = 6, |
| 269 | + SequenceParameterSet = 7, |
| 270 | + PictureParameterSet = 8, |
| 271 | + AccessUnitDelimiter = 9, |
| 272 | + EndOfSequence = 10, |
| 273 | + EndOfStream = 11, |
| 274 | + FillerData = 12, |
| 275 | + SequenceParameterSetExtension = 13, |
| 276 | + PrefixNalUnit = 14, |
| 277 | + SubsetSequenceParameterSet = 15, |
| 278 | + DepthParameterSet = 16, |
| 279 | + // 17-18 reserved |
| 280 | + CodedSliceAuxiliary = 19, |
| 281 | + CodedSliceExtension = 20, |
| 282 | + // 21-23 reserved |
| 283 | + // 24-31 unspecified |
| 284 | +} |
| 285 | + |
| 286 | +impl From<u8> for NalUnitType { |
| 287 | + fn from(value: u8) -> Self { |
| 288 | + match value { |
| 289 | + 0 => NalUnitType::Unspecified, |
| 290 | + 1 => NalUnitType::CodedSliceNonIdr, |
| 291 | + 2 => NalUnitType::CodedSliceDataPartitionA, |
| 292 | + 3 => NalUnitType::CodedSliceDataPartitionB, |
| 293 | + 4 => NalUnitType::CodedSliceDataPartitionC, |
| 294 | + 5 => NalUnitType::CodedSliceIdr, |
| 295 | + 6 => NalUnitType::Sei, |
| 296 | + 7 => NalUnitType::SequenceParameterSet, |
| 297 | + 8 => NalUnitType::PictureParameterSet, |
| 298 | + 9 => NalUnitType::AccessUnitDelimiter, |
| 299 | + 10 => NalUnitType::EndOfSequence, |
| 300 | + 11 => NalUnitType::EndOfStream, |
| 301 | + 12 => NalUnitType::FillerData, |
| 302 | + 13 => NalUnitType::SequenceParameterSetExtension, |
| 303 | + 14 => NalUnitType::PrefixNalUnit, |
| 304 | + 15 => NalUnitType::SubsetSequenceParameterSet, |
| 305 | + 16 => NalUnitType::DepthParameterSet, |
| 306 | + 19 => NalUnitType::CodedSliceAuxiliary, |
| 307 | + 20 => NalUnitType::CodedSliceExtension, |
| 308 | + _ => NalUnitType::Unspecified, |
| 309 | + } |
| 310 | + } |
| 311 | +} |
0 commit comments