videoplayer: add hardware-accelerated H.264 video decoding support
[nihav-player.git] / videoplayer / src / videodec.rs
CommitLineData
69b93cb5 1use std::thread::JoinHandle;
69b93cb5
KS
2use std::sync::mpsc::{Receiver, SyncSender, TrySendError};
3use std::thread;
4
5use sdl2::render::Texture;
6
7use nihav_core::frame::{NABufferType, NAVideoBuffer};
8use nihav_core::formats::*;
9use nihav_core::codecs::*;
10use nihav_core::scale::*;
11
4e72c04a 12use super::{DecoderStuff, DecoderType, DecoderState, DecodingState, DispQueue, FrameRecord, PktSendEvent, FRAME_QUEUE_LEN};
69b93cb5 13
4e72c04a 14static VDEC_STATE: DecoderState = DecoderState::new();
69b93cb5
KS
15
16pub const FRAME_QUEUE_SIZE: usize = 25;
17
18pub const SDL_RGB_FMT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
19 comp_info: [
20 Some(NAPixelChromaton { h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 0, next_elem: 3 }),
21 Some(NAPixelChromaton { h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 1, next_elem: 3 }),
22 Some(NAPixelChromaton { h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 2, next_elem: 3 }),
23 None, None
24 ], elem_size: 3, be: false, alpha: false, palette: false };
25
26pub struct VideoDecoder {
27 yuv_pool: NAVideoBufferPool<u8>,
28 rgb_pool: NAVideoBufferPool<u8>,
29 tb_num: u32,
30 tb_den: u32,
31 dec: DecoderStuff,
32 ifmt: NAVideoInfo,
33 scaler: NAScale,
34 ofmt_rgb: ScaleInfo,
35 ofmt_yuv: ScaleInfo,
36 oinfo_yuv: NAVideoInfo,
37 oinfo_rgb: NAVideoInfo,
38}
39
40impl VideoDecoder {
41 pub fn new(width: usize, height: usize, tb_num: u32, tb_den: u32, dec: DecoderStuff) -> Self {
42 let ofmt_rgb = ScaleInfo { width, height, fmt: SDL_RGB_FMT };
43 let ofmt_yuv = ScaleInfo { width, height, fmt: YUV420_FORMAT };
44 let oinfo_rgb = NAVideoInfo { width, height, flipped: false, format: SDL_RGB_FMT, bits: 24 };
45 let oinfo_yuv = NAVideoInfo { width, height, flipped: false, format: YUV420_FORMAT, bits: 12 };
46 Self {
47 yuv_pool: NAVideoBufferPool::new(FRAME_QUEUE_SIZE),
48 rgb_pool: NAVideoBufferPool::new(FRAME_QUEUE_SIZE),
49 tb_num, tb_den,
50 dec, ofmt_yuv, ofmt_rgb, oinfo_yuv, oinfo_rgb,
27c26a2a 51 scaler: NAScale::new(ofmt_rgb, ofmt_rgb).expect("creating scaler failed"),
69b93cb5
KS
52 ifmt: NAVideoInfo { width: 0, height: 0, flipped: false, format: SDL_RGB_FMT, bits: 24 },
53 }
54 }
55 fn convert_buf(&mut self, bt: NABufferType, ts: u64) -> Option<FrameRecord> {
27c26a2a 56 let vinfo = bt.get_video_info().expect("this should be a video buffer");
69b93cb5
KS
57 if self.ifmt.get_width() != vinfo.get_width() ||
58 self.ifmt.get_height() != vinfo.get_height() ||
59 self.ifmt.get_format() != vinfo.get_format() {
60 self.ifmt = vinfo;
61 let sc_ifmt = ScaleInfo { width: self.ifmt.get_width(), height: self.ifmt.get_height(), fmt: self.ifmt.get_format() };
bbd69555 62 let do_yuv = self.ifmt.get_format().get_model().is_yuv();
69b93cb5 63 let ofmt = if do_yuv { self.ofmt_yuv } else { self.ofmt_rgb };
27c26a2a 64 self.scaler = NAScale::new(sc_ifmt, ofmt).expect("scaling should not fail");
69b93cb5
KS
65 }
66 let mut opic = if let ColorModel::YUV(_) = self.ifmt.get_format().get_model() {
27c26a2a 67 self.yuv_pool.prealloc_video(self.oinfo_yuv, 2).expect("video frame pool allocation failure");
69b93cb5 68 while self.yuv_pool.get_free().is_none() {
4e72c04a 69 if VDEC_STATE.is_flushing() {
69b93cb5
KS
70 return None;
71 }
72 std::thread::yield_now();
73 }
27c26a2a 74 NABufferType::Video(self.yuv_pool.get_free().expect("video frame pool should have a free frame"))
69b93cb5 75 } else {
27c26a2a 76 self.rgb_pool.prealloc_video(self.oinfo_rgb, 0).expect("video frame pool allocation failure");
69b93cb5 77 while self.rgb_pool.get_free().is_none() {
4e72c04a 78 if VDEC_STATE.is_flushing() {
69b93cb5
KS
79 return None;
80 }
81 std::thread::yield_now();
82 }
27c26a2a 83 NABufferType::VideoPacked(self.rgb_pool.get_free().expect("video frame pool should have a free frame"))
69b93cb5
KS
84 };
85 let ret = self.scaler.convert(&bt, &mut opic);
86 if ret.is_err() { println!(" scaler error {:?}", ret.err()); return None; }
87 ret.unwrap();
88 let time = NATimeInfo::ts_to_time(ts, 1000, self.tb_num, self.tb_den);
89 Some((opic, time))
90 }
91 pub fn next_frame(&mut self, pkt: &NAPacket) -> Option<FrameRecord> {
37f130a7
KS
92 match self.dec.dec {
93 DecoderType::Video(ref mut vdec, ref mut reord) => {
94 if let Ok(frm) = vdec.decode(&mut self.dec.dsupp, pkt) {
95 reord.add_frame(frm);
96 while let Some(frm) = reord.get_frame() {
97 let bt = frm.get_buffer();
98 if let NABufferType::None = bt { continue; }
99 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
100 return self.convert_buf(bt, ts);
101 }
102 }
103 },
104 DecoderType::VideoMT(ref mut vdec, ref mut reord) => {
105 let queue_id = reord.register_frame();
bbd69555 106 match vdec.queue_pkt(&mut self.dec.dsupp, pkt, queue_id) {
37f130a7
KS
107 Ok(true) => {},
108 Ok(false) => {
109 while !vdec.can_take_input() || vdec.has_output() {
110 match vdec.get_frame() {
111 (Ok(frm), id) => {
112 reord.add_frame(frm, id);
113 },
114 (Err(err), id) => {
115 reord.drop_frame(id);
1e14f1e2
KS
116 if err != DecoderError::MissingReference {
117 println!("frame {} decoding error {:?}", id, err);
118 }
37f130a7
KS
119 },
120 };
121 }
bbd69555 122 match vdec.queue_pkt(&mut self.dec.dsupp, pkt, queue_id) {
37f130a7 123 Ok(true) => {},
364f01a3
KS
124 Ok(false) => {
125 println!("still can't queue frame!");
126 VDEC_STATE.set_state(DecodingState::Error);
127 },
128 Err(err) => println!("queueing error {:?}", err),
37f130a7
KS
129 };
130 },
364f01a3 131 Err(err) => println!("queueing error {:?}", err),
37f130a7
KS
132 };
133 while let Some(frm) = reord.get_frame() {
134 let bt = frm.get_buffer();
135 if let NABufferType::None = bt { continue; }
136 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
137 return self.convert_buf(bt, ts);
138 }
139 },
35d0d63a
KS
140 #[cfg(feature="hwaccel")]
141 DecoderType::VideoHW(ref mut vdec) => {
142 let _ = vdec.queue_pkt(pkt);
143 while let Some(frm) = vdec.get_frame() {
144 let bt = frm.get_buffer();
145 if let NABufferType::None = bt { continue; }
146 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
147 return self.convert_buf(bt, ts);
148 }
149 },
37f130a7
KS
150 _ => panic!("not a video decoder!"),
151 };
152 None
153 }
154 pub fn more_frames(&mut self, do_not_wait: bool) -> Option<FrameRecord> {
155 match self.dec.dec {
156 DecoderType::Video(ref mut _dec, ref mut reord) => {
157 while let Some(frm) = reord.get_frame() {
158 let bt = frm.get_buffer();
159 if let NABufferType::None = bt { continue; }
160 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
161 return self.convert_buf(bt, ts);
162 }
163 },
164 DecoderType::VideoMT(ref mut vdec, ref mut reord) => {
165 let mut got_some = false;
166 while vdec.has_output() {
167 match vdec.get_frame() {
168 (Ok(frm), id) => {
169 reord.add_frame(frm, id);
170 got_some = true;
171 },
172 (Err(err), id) => {
173 reord.drop_frame(id);
1e14f1e2
KS
174 if err != DecoderError::MissingReference {
175 println!("frame {} decoding error {:?}", id, err);
176 }
37f130a7
KS
177 },
178 };
179 }
180 if !got_some && !do_not_wait {
181 match vdec.get_frame() {
182 (Ok(frm), id) => {
183 reord.add_frame(frm, id);
184 },
185 (Err(DecoderError::NoFrame), _) => {},
186 (Err(err), id) => {
187 reord.drop_frame(id);
1e14f1e2
KS
188 if err != DecoderError::MissingReference {
189 println!("frame {} decoding error {:?}", id, err);
190 }
37f130a7
KS
191 },
192 };
193 }
194 while let Some(frm) = reord.get_frame() {
195 let bt = frm.get_buffer();
196 if let NABufferType::None = bt { continue; }
197 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
198 return self.convert_buf(bt, ts);
199 }
200 },
35d0d63a
KS
201 #[cfg(feature="hwaccel")]
202 DecoderType::VideoHW(ref mut vdec) => {
203 while let Some(frm) = vdec.get_frame() {
204 let bt = frm.get_buffer();
205 if let NABufferType::None = bt { continue; }
206 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
207 return self.convert_buf(bt, ts);
208 }
209 },
37f130a7
KS
210 _ => {},
211 };
69b93cb5
KS
212 None
213 }
214 pub fn last_frame(&mut self) -> Option<FrameRecord> {
37f130a7
KS
215 match self.dec.dec {
216 DecoderType::Video(ref mut _dec, ref mut reord) => {
217 while let Some(frm) = reord.get_last_frames() {
218 let bt = frm.get_buffer();
219 if let NABufferType::None = bt { continue; }
220 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
221 return self.convert_buf(bt, ts);
222 }
223 },
224 DecoderType::VideoMT(ref mut _dec, ref mut reord) => {
225 while let Some(frm) = reord.get_last_frames() {
226 let bt = frm.get_buffer();
227 if let NABufferType::None = bt { continue; }
228 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
229 return self.convert_buf(bt, ts);
230 }
231 },
35d0d63a
KS
232 #[cfg(feature="hwaccel")]
233 DecoderType::VideoHW(ref mut dec) => {
234 while let Some(frm) = dec.get_last_frames() {
235 let bt = frm.get_buffer();
236 if let NABufferType::None = bt { continue; }
237 let ts = frm.get_dts().unwrap_or_else(|| frm.get_pts().unwrap_or(0));
238 return self.convert_buf(bt, ts);
239 }
240 },
37f130a7
KS
241 _ => {},
242 };
69b93cb5
KS
243 None
244 }
245 pub fn flush(&mut self) {
37f130a7
KS
246 match self.dec.dec {
247 DecoderType::Video(ref mut dec, ref mut reord) => {
248 dec.flush();
249 reord.flush();
250 },
251 DecoderType::VideoMT(ref mut dec, ref mut reord) => {
252 dec.flush();
253 reord.flush();
254 },
35d0d63a
KS
255 #[cfg(feature="hwaccel")]
256 DecoderType::VideoHW(ref mut dec) => {
257 dec.flush();
258 },
37f130a7
KS
259 _ => {},
260 };
69b93cb5
KS
261 }
262}
263
264fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, video_dec: DecoderStuff, vprecv: Receiver<PktSendEvent>, vfsend: SyncSender<(NABufferType, u64)>) -> JoinHandle<()> {
265 std::thread::Builder::new().name("vdecoder".to_string()).spawn(move ||{
4e72c04a 266 VDEC_STATE.set_state(DecodingState::Waiting);
69b93cb5
KS
267 let mut vdec = VideoDecoder::new(width, height, tb_num, tb_den, video_dec);
268 let mut skip_mode = FrameSkipMode::None;
269 loop {
270 match vprecv.recv() {
271 Ok(PktSendEvent::Packet(pkt)) => {
4e72c04a 272 if !VDEC_STATE.is_flushing() {
69b93cb5 273 if let Some((buf, time)) = vdec.next_frame(&pkt) {
27c26a2a 274 vfsend.send((buf, time)).expect("video frame should be sent");
69b93cb5 275 }
37f130a7 276 while let Some((buf, time)) = vdec.more_frames(true) {
27c26a2a 277 vfsend.send((buf, time)).expect("video frame should be sent");
37f130a7
KS
278 }
279 }
280 },
281 Ok(PktSendEvent::GetFrames) => {
282 while let Some((buf, time)) = vdec.more_frames(false) {
27c26a2a 283 vfsend.send((buf, time)).expect("video frame should be sent");
69b93cb5 284 }
4e72c04a 285 VDEC_STATE.set_state(DecodingState::Waiting);
69b93cb5
KS
286 },
287 Ok(PktSendEvent::Flush) => {
288 vdec.flush();
4e72c04a 289 VDEC_STATE.set_state(DecodingState::Waiting);
69b93cb5
KS
290 },
291 Ok(PktSendEvent::End) => {
292 while vdec.yuv_pool.get_free().is_some() && vdec.rgb_pool.get_free().is_some() {
27c26a2a
KS
293 if let Some(frm) = vdec.last_frame() {
294 vfsend.send(frm).expect("video frame should be sent");
295 } else {
69b93cb5
KS
296 break;
297 }
69b93cb5 298 }
4e72c04a 299 VDEC_STATE.set_state(DecodingState::End);
69b93cb5
KS
300 break;
301 },
302 Ok(PktSendEvent::ImmediateEnd) => {
4e72c04a 303 VDEC_STATE.set_state(DecodingState::End);
69b93cb5
KS
304 break;
305 },
306 Ok(PktSendEvent::HurryUp) => {
307 skip_mode = skip_mode.advance();
37f130a7 308 if let DecoderType::Video(ref mut dec, ref mut _reord) = vdec.dec.dec {
31611a29 309 println!("setting hurry up mode to {}", skip_mode.to_string());
37f130a7 310 dec.set_options(&[NAOption{
69b93cb5
KS
311 name: FRAME_SKIP_OPTION,
312 value: NAValue::String(skip_mode.to_string()),
313 }]);
37f130a7 314 }
69b93cb5
KS
315 },
316 Err(_) => {
317 break;
318 },
319 };
320 }
321 }).unwrap()
322}
323
324trait Advance {
325 fn advance(&self) -> Self;
326}
327
328impl Advance for FrameSkipMode {
329 fn advance(&self) -> Self {
330 match *self {
331 FrameSkipMode::None => FrameSkipMode::KeyframesOnly,
332 FrameSkipMode::KeyframesOnly => FrameSkipMode::IntraOnly,
333 FrameSkipMode::IntraOnly => FrameSkipMode::None,
334 }
335 }
336}
337
338fn output_yuv(yuv_texture: &mut Texture, buf: &NAVideoBuffer<u8>, width: usize, height: usize) {
339 let src = buf.get_data();
340 let ysstride = buf.get_stride(0);
341 let ysrc = &src[buf.get_offset(0)..];
342 let usstride = buf.get_stride(2);
343 let usrc = &src[buf.get_offset(2)..];
344 let vsstride = buf.get_stride(1);
345 let vsrc = &src[buf.get_offset(1)..];
346 yuv_texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
347 let csize = pitch.min(width);
348 for (dline, sline) in buffer.chunks_exact_mut(pitch).take(height).zip(ysrc.chunks_exact(ysstride)) {
349 dline[..csize].copy_from_slice(&sline[..csize]);
350 }
351 let coff = pitch * height;
352 let csize = (pitch / 2).min(width / 2);
353 for (dline, sline) in buffer[coff..].chunks_exact_mut(pitch / 2).take(height/2).zip(vsrc.chunks(vsstride)) {
354 dline[..csize].copy_from_slice(&sline[..csize]);
355 }
356 let coff = pitch * height + (pitch / 2) * (height / 2);
357 for (dline, sline) in buffer[coff..].chunks_exact_mut(pitch / 2).take(height/2).zip(usrc.chunks(usstride)) {
358 dline[..csize].copy_from_slice(&sline[..csize]);
359 }
27c26a2a 360 }).expect("surface should be locked");
69b93cb5
KS
361}
362
363
364pub struct VideoControl {
365 vqueue: Vec<PktSendEvent>,
366 vpsend: SyncSender<PktSendEvent>,
367 vfrecv: Receiver<FrameRecord>,
368 do_yuv: bool,
369 vthread: JoinHandle<()>,
370}
371
372impl VideoControl {
373 pub fn new(video_dec: Option<DecoderStuff>, width: usize, height: usize, tb_num: u32, tb_den: u32) -> Self {
374 let (vpsend, vprecv) = std::sync::mpsc::sync_channel::<PktSendEvent>(0);
375 let (vfsend, vfrecv) = std::sync::mpsc::sync_channel::<FrameRecord>(FRAME_QUEUE_SIZE - 1);
376
4e72c04a 377 VDEC_STATE.set_state(DecodingState::Normal);
69b93cb5
KS
378
379 let vthread = if let Some(video_dec) = video_dec {
380 start_video_decoding(width, height, tb_num, tb_den, video_dec, vprecv, vfsend)
381 } else {
382 thread::Builder::new().name("vdecoder-dummy".to_string()).spawn(move ||{
383 loop {
384 match vprecv.recv() {
385 Ok(PktSendEvent::End) => break,
386 Ok(PktSendEvent::ImmediateEnd) => break,
387 Err(_) => {
388 break;
389 },
390 _ => {},
391 };
392 }
4e72c04a 393 VDEC_STATE.set_state(DecodingState::End);
69b93cb5
KS
394 }).unwrap()
395 };
396
397
398 Self {
399 vqueue: Vec::with_capacity(FRAME_QUEUE_LEN),
400 vpsend, vfrecv,
401 do_yuv: false,
402 vthread,
403 }
404 }
405 pub fn flush(&mut self) {
b5053bfc 406 self.vqueue.clear();
4e72c04a 407 VDEC_STATE.set_state(DecodingState::Flush);
69b93cb5
KS
408 for _ in 0..8 {
409 let _ = self.vfrecv.try_recv();
410 }
411 let _ = self.vpsend.send(PktSendEvent::Flush);
412 while self.vfrecv.try_recv().is_ok() { }
413 }
414 pub fn get_queue_size(&self) -> usize { self.vqueue.len() }
415 pub fn is_filled(&self, size: usize) -> bool {
416 self.vqueue.len() >= size
417 }
418 pub fn try_send_video(&mut self, evt: PktSendEvent) -> bool {
bbd69555 419 if !self.vqueue.is_empty() {
69b93cb5
KS
420 self.vqueue.push(evt);
421 false
422 } else {
423 self.try_send_event(evt)
424 }
425 }
426 fn try_send_event(&mut self, evt: PktSendEvent) -> bool {
427 if let Err(TrySendError::Full(evt)) = self.vpsend.try_send(evt) {
428 self.vqueue.insert(0, evt);
429 false
430 } else {
431 true
432 }
433 }
434 pub fn try_send_queued(&mut self) -> bool {
435 while !self.vqueue.is_empty() {
436 let pkt = self.vqueue.remove(0);
437 if !self.try_send_event(pkt) {
438 return false;
439 }
440 }
441 true
442 }
443 pub fn is_video_end(&self) -> bool {
4e72c04a 444 matches!(VDEC_STATE.get_state(), DecodingState::End | DecodingState::Error)
69b93cb5 445 }
4e72c04a
KS
446 pub fn wait_for_frames(&mut self) -> Result<(), ()> {
447 VDEC_STATE.set_state(DecodingState::Prefetch);
37f130a7
KS
448 self.try_send_event(PktSendEvent::GetFrames);
449 while !self.try_send_queued() {
450 }
4e72c04a
KS
451 loop {
452 match VDEC_STATE.get_state() {
453 DecodingState::Waiting => {
454 VDEC_STATE.set_state(DecodingState::Normal);
455 return Ok(());
456 },
457 DecodingState::Prefetch => thread::yield_now(),
458 _ => return Err(()),
459 };
37f130a7
KS
460 }
461 }
69b93cb5
KS
462
463 pub fn is_yuv(&self) -> bool { self.do_yuv }
464
465 pub fn fill(&mut self, disp_queue: &mut DispQueue) {
466 while !disp_queue.is_full() {
467 let is_empty = disp_queue.is_empty();
468 if let Ok((pic, time)) = self.vfrecv.try_recv() {
27c26a2a 469 let buf = pic.get_vbuf().expect("video frame should be of u8 type");
69b93cb5
KS
470 self.do_yuv = buf.get_info().get_format().get_model().is_yuv();
471 let idx = disp_queue.end;
472 disp_queue.move_end();
473 let frm = &mut disp_queue.pool[idx];
474 if !self.do_yuv {
475 let sstride = buf.get_stride(0);
476 let src = buf.get_data();
477 frm.rgb_tex.with_lock(None, |buffer: &mut [u8], pitch: usize| {
478 let csize = sstride.min(pitch);
479 for (dst, src) in buffer.chunks_mut(pitch).zip(src.chunks(sstride)) {
bbd69555 480 dst[..csize].copy_from_slice(&src[..csize]);
69b93cb5
KS
481 }
482 true
27c26a2a 483 }).expect("surface should be locked");
69b93cb5
KS
484 } else {
485 output_yuv(&mut frm.yuv_tex, &buf, disp_queue.width, disp_queue.height);
486 }
487 frm.valid = true;
488 frm.is_yuv = self.do_yuv;
489 frm.ts = time;
490 if is_empty {
491 disp_queue.first_ts = time;
492 }
493 disp_queue.last_ts = time;
494 } else {
495 break;
496 }
497 }
498 }
499
500 pub fn finish(self) {
4e72c04a 501 VDEC_STATE.set_state(DecodingState::Flush);
69b93cb5
KS
502 for _ in 0..8 {
503 let _ = self.vfrecv.try_recv();
504 }
505 let _ = self.vpsend.send(PktSendEvent::ImmediateEnd);
506 self.vthread.join().unwrap();
507 }
508}