]> git.nihav.org Git - nihav-encoder.git/commitdiff
Create scaler when input video format differs from the expected output format
authorKostya Shishkov <kostya.shishkov@gmail.com>
Tue, 31 Mar 2026 15:46:02 +0000 (17:46 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Tue, 31 Mar 2026 15:46:02 +0000 (17:46 +0200)
src/transcoder.rs

index a90484b36f79a0b5a3a59a84554aa87d86f2626f..4a164b2b04fa68c83eba526ee1b02c0152132db4 100644 (file)
@@ -226,6 +226,7 @@ impl EncoderInterface for AudioEncodeContext {
 
 pub struct VideoEncodeContext {
     pub encoder:    Box<dyn NAEncoder>,
+    pub vinfo:      NAVideoInfo,
     pub scaler:     Option<NAScale>,
     pub scaler_buf: NABufferType,
     pub tb_num:     u32,
@@ -237,6 +238,31 @@ pub struct VideoEncodeContext {
 impl EncoderInterface for VideoEncodeContext {
     fn encode_frame(&mut self, dst_id: u32, frm: NAFrameRef, scale_opts: &[(String, String)], queue: &mut OutputQueue, dbg: &mut Option<DebugLog>) -> EncoderResult<bool> {
         let buf = frm.get_buffer();
+        if let Some(vinfo) = buf.get_video_info() {
+            if self.scaler.is_none() && vinfo != self.vinfo {
+                let ifmt = get_scale_fmt_from_pic(&buf);
+                let ofmt = ScaleInfo {
+                        width:  self.vinfo.width,
+                        height: self.vinfo.height,
+                        fmt:    self.vinfo.format,
+                    };
+                if let Some(ref mut dlog) = dbg {
+                    dlog.log(DebugLog::ENCODE, &format!("Input for the output stream {dst_id} differs in format, inserting scaler"));
+                }
+                if let Ok(scaler) = NAScale::new_with_options(ifmt, ofmt, scale_opts) {
+                    self.scaler = Some(scaler);
+                    self.scaler_buf = if let Ok(buf) = alloc_video_buffer(self.vinfo, 4) {
+                            buf
+                        } else {
+                            println!("cannot create scaler buffer");
+                            return Err(EncoderError::AllocError);
+                        };
+                } else {
+                    println!("error re-initialising scaler for {ifmt} -> {ofmt}");
+                    return Err(EncoderError::InvalidParameters);
+                }
+            }
+        }
         let cbuf = if let NABufferType::None = buf {
             if (self.encoder.get_capabilities() & ENC_CAPS_SKIPFRAME) == 0 {
                 if let NABufferType::None = self.scaler_buf {
@@ -963,6 +989,7 @@ impl Transcoder {
                             if svinfo == dvinfo && !forced_out {
                                 Box::new(VideoEncodeContext {
                                     encoder,
+                                    vinfo: *dvinfo,
                                     scaler: None,
                                     scaler_buf: NABufferType::None,
                                     cfr: force_cfr,
@@ -986,6 +1013,7 @@ impl Transcoder {
                                 let scaler_buf = ret.unwrap();
                                 Box::new(VideoEncodeContext {
                                     encoder,
+                                    vinfo: *dvinfo,
                                     scaler: Some(scaler),
                                     scaler_buf,
                                     cfr: force_cfr,
@@ -1144,6 +1172,7 @@ println!("encoder {} is not supported by output (expected {})", istr.id, istr.ge
                         if svinfo == dvinfo {
                             Box::new(VideoEncodeContext {
                                 encoder,
+                                vinfo: *dvinfo,
                                 scaler: None,
                                 scaler_buf: NABufferType::None,
                                 cfr: force_cfr,
@@ -1167,6 +1196,7 @@ println!("encoder {} is not supported by output (expected {})", istr.id, istr.ge
                             let scaler_buf = ret.unwrap();
                             Box::new(VideoEncodeContext {
                                 encoder,
+                                vinfo: *dvinfo,
                                 scaler: Some(scaler),
                                 scaler_buf,
                                 cfr: force_cfr,