use std::ptr::null_mut; use std::sync::Condvar; use std::thread::ThreadId; use libc::{EAGAIN, endservent}; use rsmpeg::avcodec::{AVCodecContext, AVPacket}; use rsmpeg::avutil::{av_rescale_q, AVFrame}; use rsmpeg::error::RsmpegError; use rsmpeg::error::RsmpegError::AVError; use rsmpeg::ffi::{AV_NOPTS_VALUE, AVERROR_EOF}; use crate::playback::DECODER_REORDER_PTS; use crate::playback::packet::MutexPacketQueue; use rsmpeg::ffi::{ AVRational, avcodec_flush_buffers }; pub struct Decoder { pkt : Box, queue : Box, avctx : Box, pkt_serial : Box, finished: i64, packet_pending: bool, empty_queue_cond: Box, start_pts : i64, start_pts_tb : AVRational, next_pts : i64, next_pts_tb: AVRational, decoder_tid: Box, } impl Decoder { fn new(avctx: AVCodecContext, queue: MutexPacketQueue, tid: ThreadId) -> Self { Decoder { pkt: Box::new(Default::default()), queue: Box::new(queue), avctx: Box::new(avctx), pkt_serial: Box::new(0), finished: 0, packet_pending: false, empty_queue_cond: Box::new(Default::default()), start_pts: 0, start_pts_tb: AVRational {num: 1, den : 1}, next_pts: 0, next_pts_tb: AVRational {num : 1, den : 1}, decoder_tid: Box::new(tid), } } pub fn decode_frame(&mut self, av_frame: &mut AVFrame, sub: &mut rsmpeg::ffi::AVSubtitle) -> Result<(),RsmpegError> { // TODO Recheck let mut ret = Err(AVError(EAGAIN)); loop { if self.queue.data.serial == *self.pkt_serial { loop { if self.queue.data.abort_request { return Err(AVError(-1)); } let codec_type = self.avctx.extract_codecpar().codec_type(); ret = if codec_type.is_video() { let ret_receive = self.avctx.receive_frame(); if let Ok(mut frame) = ret_receive { if ! DECODER_REORDER_PTS { frame.set_pts(frame.best_effort_timestamp); } else { frame.set_pts(frame.pkt_dts); } *av_frame = frame; Ok(()) } else { Err(ret_receive.unwrap_err()) } } else if codec_type.is_audio() { let ret_receive = self.avctx.receive_frame(); if let Ok(mut frame) = ret_receive { let tb = AVRational {num: 1, den: frame.sample_rate}; if frame.pts != AV_NOPTS_VALUE { frame.set_pts(av_rescale_q(frame.pts, self.avctx.pkt_timebase, tb)) } else if self.next_pts != AV_NOPTS_VALUE { frame.set_pts(av_rescale_q(self.next_pts, self.next_pts_tb, tb)); } if frame.pts != AV_NOPTS_VALUE { self.next_pts = frame.pts + frame.nb_samples as i64; self.next_pts_tb = tb; } *av_frame = frame; Ok(()) } else { Err(ret_receive.unwrap_err()) } } else { ret }; if Some(&AVError(AVERROR_EOF)) == ret.as_ref().err(){ self.finished = *self.pkt_serial; unsafe { avcodec_flush_buffers(self.avctx.as_mut_ptr())}; return Ok(()); // TODO } if let Some(&AVError(x)) = ret.as_ref().err() { if x >= 0 { return Err(AVError(1)) } } if Some(&AVError(EAGAIN)) == ret.as_ref().err() { break; } } } loop { { let mut pq = self.queue.mutex.lock().unwrap(); while self.queue.data.queue.len() == 0 { pq = self.empty_queue_cond.wait(pq).unwrap(); } } if ! self.packet_pending { let old_serial = *self.pkt_serial; // if packet_queue_get(&d.queue, &mut d.pkt, true, Some(&mut d.pkt_serial)) < 0 {// TODO if let Some(AVError(x)) = &mut self.queue.get( &mut self.pkt, true, Some(&mut self.pkt_serial)).err(){// TODO if (*x as i32) < 0 { return Err(AVError(-1)); } } if old_serial != *self.pkt_serial { unsafe { avcodec_flush_buffers(self.avctx.as_mut_ptr())}; self.finished = 0; self.next_pts = self.start_pts; self.next_pts_tb = self.start_pts_tb; } } { if self.queue.data.serial == *self.pkt_serial { break; } } // // TODO av_packet_unref(d->pkt); } if self.avctx.extract_codecpar().codec_type().is_subtitle() { let got_frame = 0; let mut ret = self.avctx.decode_subtitle(Some(&mut *self.pkt)); // TODO no return ? if ret.is_err() { ret = Err(AVError(EAGAIN)); } else { if ret.as_ref().unwrap().is_some() && self.pkt.data != null_mut() { // *sub = *ret.unwrap().unwrap(); FIXME self.packet_pending = true; } ret = if ret.as_ref().unwrap().is_some() { Ok(None) } else { if self.pkt.data != null_mut() { Err(AVError(EAGAIN)) } else { Err(AVError(AVERROR_EOF)) } }; //av_packet_unref(d->pkt); } } else { if self.avctx.send_packet(Some(&self.pkt)).err() == Some(AVError(EAGAIN)) { //av_log(&d.avctx, AV_LOG_ERROR, // "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n"); self.packet_pending = true; } else { //av_packet_unref(d->pkt); } } } } }