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