1use std::collections::BinaryHeap;
19use std::collections::VecDeque;
20
21use oxideav_core::{
22 CodecId, CodecParameters, Decoder, Error, Frame, Packet, Result, VideoFrame, VideoPlane,
23};
24
25use crate::hvcc::{extradata_is_hvcc, parse_hvcc, split_length_prefixed};
26use crate::picture::{Picture, Plane};
27use crate::sequence::{DecodedFrame, SequenceDecoder};
28
29const DEFAULT_REORDER: usize = 8;
32
33pub struct H265Decoder {
35 codec_id: CodecId,
36 seq: SequenceDecoder,
37 reorder: Vec<DecodedFrame>,
40 ready: VecDeque<Frame>,
42 pts_queue: BinaryHeap<std::cmp::Reverse<i64>>,
44 nal_length_size: Option<usize>,
49 flushed: bool,
50}
51
52impl std::fmt::Debug for H265Decoder {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 f.debug_struct("H265Decoder")
55 .field("codec_id", &self.codec_id)
56 .field("reorder", &self.reorder.len())
57 .field("ready", &self.ready.len())
58 .finish()
59 }
60}
61
62pub fn make_decoder(params: &CodecParameters) -> Result<Box<dyn Decoder>> {
72 let mut seq = SequenceDecoder::new();
73 let mut nal_length_size = None;
74 if !params.extradata.is_empty() {
75 if extradata_is_hvcc(¶ms.extradata) {
76 let rec = parse_hvcc(¶ms.extradata)
78 .map_err(|e| Error::InvalidData(format!("h265 hvcC extradata: {e}")))?;
79 for unit in rec.nal_units {
80 seq.push_nal_unit(unit)
81 .map_err(|e| Error::InvalidData(format!("h265 hvcC extradata: {e}")))?;
82 }
83 nal_length_size = Some(rec.length_size);
84 } else {
85 seq.push_annexb(¶ms.extradata)
87 .map_err(|e| Error::InvalidData(format!("h265 extradata: {e}")))?;
88 }
89 }
90 Ok(Box::new(H265Decoder {
91 codec_id: params.codec_id.clone(),
92 seq,
93 reorder: Vec::new(),
94 ready: VecDeque::new(),
95 pts_queue: BinaryHeap::new(),
96 nal_length_size,
97 flushed: false,
98 }))
99}
100
101impl H265Decoder {
102 fn drain(&mut self, flush: bool) {
105 self.reorder.extend(self.seq.take_decoded());
106 self.reorder.sort_by_key(|f| (f.cvs_index, f.poc));
107 let depth = if flush {
108 0
109 } else {
110 self.seq
111 .max_num_reorder_pics()
112 .map_or(DEFAULT_REORDER, |n| n as usize)
113 };
114 while self.reorder.len() > depth {
115 let f = self.reorder.remove(0);
116 if !f.output {
117 continue;
118 }
119 let pts = self.pts_queue.pop().map(|r| r.0);
120 self.ready
121 .push_back(Frame::Video(video_frame(&f.picture, pts)));
122 }
123 }
124}
125
126impl Decoder for H265Decoder {
127 fn codec_id(&self) -> &CodecId {
128 &self.codec_id
129 }
130
131 fn send_packet(&mut self, packet: &Packet) -> Result<()> {
132 if packet.data.is_empty() {
133 return self.flush();
135 }
136 if let Some(pts) = packet.pts {
137 self.pts_queue.push(std::cmp::Reverse(pts));
138 }
139 if let Some(length_size) = self.nal_length_size {
140 let units = split_length_prefixed(&packet.data, length_size)
141 .map_err(|e| Error::InvalidData(format!("h265 decode: {e}")))?;
142 for unit in units {
143 self.seq
144 .push_nal_unit(unit)
145 .map_err(|e| Error::InvalidData(format!("h265 decode: {e}")))?;
146 }
147 } else {
148 self.seq
149 .push_annexb(&packet.data)
150 .map_err(|e| Error::InvalidData(format!("h265 decode: {e}")))?;
151 }
152 self.drain(false);
153 Ok(())
154 }
155
156 fn receive_frame(&mut self) -> Result<Frame> {
157 if let Some(f) = self.ready.pop_front() {
158 return Ok(f);
159 }
160 if self.flushed {
161 if !self.reorder.is_empty() {
162 self.drain(true);
163 if let Some(f) = self.ready.pop_front() {
164 return Ok(f);
165 }
166 }
167 return Err(Error::Eof);
168 }
169 Err(Error::NeedMore)
170 }
171
172 fn flush(&mut self) -> Result<()> {
173 self.seq
175 .flush()
176 .map_err(|e| Error::InvalidData(format!("h265 flush: {e}")))?;
177 self.flushed = true;
178 self.drain(true);
179 Ok(())
180 }
181}
182
183fn video_frame(pic: &Picture, pts: Option<i64>) -> VideoFrame {
187 let planes = if pic.chroma_array_type() == 0 {
188 vec![Plane::Luma]
189 } else {
190 vec![Plane::Luma, Plane::Cb, Plane::Cr]
191 };
192 let wide = pic.bit_depth(Plane::Luma) > 8
193 || (pic.chroma_array_type() != 0 && pic.bit_depth(Plane::Cb) > 8);
194 let mut out = Vec::with_capacity(planes.len());
195 for plane in planes {
196 let (w, h) = pic.plane_dims(plane);
197 let buf = pic.plane(plane);
198 let mut data;
199 let stride;
200 if wide {
201 stride = w * 2;
202 data = Vec::with_capacity(w * h * 2);
203 for &v in buf.iter().take(w * h) {
204 data.extend_from_slice(&(v as u16).to_le_bytes());
205 }
206 } else {
207 stride = w;
208 data = Vec::with_capacity(w * h);
209 data.extend(buf.iter().take(w * h).map(|&v| v as u8));
210 }
211 out.push(VideoPlane { stride, data });
212 }
213 VideoFrame { pts, planes: out }
214}