Advertisement
Guest User

Untitled

a guest
Oct 4th, 2023
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 12.67 KB | None | 0 0
  1. use ffmpeg::{
  2.     decoder, encoder,
  3.     error::EAGAIN,
  4.     format::context::{Input, Output},
  5.     media::Type,
  6.     packet::{Mut, Ref},
  7.     util::frame::video::Video,
  8.     Codec, Packet, Rational,
  9. };
  10. use ffmpeg_next as ffmpeg;
  11. use ffmpeg_sys_next::{
  12.     av_calloc, av_dump_format, av_frame_alloc, av_frame_unref, av_guess_format,
  13.     av_interleaved_write_frame, av_malloc, av_mallocz, av_packet_alloc,
  14.     av_packet_unref, av_read_frame, av_write_trailer, avcodec_alloc_context3,
  15.     avcodec_find_decoder, avcodec_find_encoder, avcodec_open2,
  16.     avcodec_parameters_from_context, avcodec_parameters_to_context,
  17.     avcodec_receive_frame, avcodec_receive_packet, avcodec_send_frame,
  18.     avcodec_send_packet, avformat_alloc_context,
  19.     avformat_alloc_output_context2, avformat_free_context,
  20.     avformat_init_output, avformat_new_stream, avformat_open_input,
  21.     avformat_write_header, avio_alloc_context, AVCodecContext,
  22.     AVCodecParameters, AVFormatContext, AVMediaType, AVERROR, AVERROR_EOF,
  23.     AVFMT_FLAG_CUSTOM_IO, AVSEEK_SIZE, SEEK_CUR, SEEK_SET,
  24. };
  25. use core::panic;
  26. use std::{
  27.     ffi::{c_int, c_uchar, c_void, CString},
  28.     fs::File,
  29.     io::{Read, Seek},
  30.     mem::{forget, size_of},
  31.     ptr,
  32. };
  33.  
  34. const MPEG_TS_PACKET_SIZE: usize = 188;
  35.  
  36. struct Wrapper<T> {
  37.     inner: T,
  38. }
  39.  
  40. extern "C" fn read(
  41.     opaque: *mut c_void,
  42.     buf: *mut u8,
  43.     buf_size: c_int,
  44. ) -> c_int {
  45.     let input: Box<Wrapper<Box<dyn Read>>> =
  46.         unsafe { Box::from_raw(opaque as *mut Wrapper<Box<dyn Read>>) };
  47.     let input = Box::leak(input);
  48.     let mut buffer =
  49.         unsafe { std::slice::from_raw_parts_mut(buf, buf_size as usize) };
  50.     let mut read: c_int = 0;
  51.     loop {
  52.         match (&mut input.inner).read(&mut buffer) {
  53.             Ok(0) => break,
  54.             Ok(n) => {
  55.                 read += n as c_int;
  56.                 buffer = &mut buffer[n..];
  57.             }
  58.             Err(err) => {
  59.                 if let Some(code) = err.raw_os_error() {
  60.                     return code;
  61.                 }
  62.             }
  63.         }
  64.         if buffer.is_empty() {
  65.             break;
  66.         }
  67.     }
  68.     if read == 0 {
  69.         return AVERROR_EOF;
  70.     }
  71.     return read;
  72. }
  73.  
  74. extern "C" fn write(
  75.     opaque: *mut c_void,
  76.     buf: *mut u8,
  77.     buf_size: c_int,
  78. ) -> c_int {
  79.     let output: Box<Wrapper<Box<dyn SeekWrite>>> =
  80.         unsafe { Box::from_raw(opaque as *mut Wrapper<Box<dyn SeekWrite>>) };
  81.     let output = Box::leak(output);
  82.     let mut written: c_int = 0;
  83.     let mut buffer =
  84.         unsafe { std::slice::from_raw_parts(buf, buf_size as usize) };
  85.     loop {
  86.         match output.inner.write(buffer) {
  87.             Ok(n) => {
  88.                 written += n as c_int;
  89.                 buffer = &buffer[n..];
  90.             }
  91.             Err(err) => {
  92.                 if let Some(code) = err.raw_os_error() {
  93.                     return code;
  94.                 }
  95.             }
  96.         }
  97.         if buffer.is_empty() {
  98.             break;
  99.         }
  100.     }
  101.     return written;
  102. }
  103.  
  104. unsafe extern "C" fn seek(
  105.     opaque: *mut c_void,
  106.     offset: i64,
  107.     whence: c_int,
  108. ) -> i64 {
  109.     let output: Box<Wrapper<Box<dyn SeekWrite>>> =
  110.         unsafe { Box::from_raw(opaque as *mut Wrapper<Box<dyn SeekWrite>>) };
  111.     let output = Box::leak(output);
  112.     match whence {
  113.         AVSEEK_SIZE => -1,
  114.         SEEK_SET => {
  115.             match output.inner.seek(std::io::SeekFrom::Start(offset as u64)) {
  116.                 Ok(n) => n as i64,
  117.                 Err(err) => {
  118.                     err.raw_os_error().map(Into::into).unwrap_or(-1)
  119.                 },
  120.             }
  121.         }
  122.         SEEK_CUR => {
  123.             match output.inner.seek(std::io::SeekFrom::Current(offset)) {
  124.                 Ok(n) => n as i64,
  125.                 Err(err) => {
  126.                     err.raw_os_error().map(Into::into).unwrap_or(-1)
  127.                 },
  128.             }
  129.  
  130.         }
  131.         SEEK_END => {
  132.             match output.inner.seek(std::io::SeekFrom::End(offset)) {
  133.                 Ok(n) => return n as i64,
  134.                 Err(err) => {
  135.                     err.raw_os_error().map(Into::into).unwrap_or(-1)
  136.                 },
  137.             }
  138.         }
  139.         _ => { -1 }
  140.     }
  141. }
  142.  
  143. use std::io::Write;
  144.  
  145. fn pgm_save(frame: &Video, filename: &str) {
  146.     let mut file = std::fs::OpenOptions::new()
  147.         .create(true)
  148.         .truncate(true)
  149.         .write(true)
  150.         .open(filename)
  151.         .unwrap();
  152.  
  153.     write!(file, "P5\n{} {}\n{}\n", frame.width(), frame.height(), 255)
  154.         .unwrap();
  155.     let wrap = frame.stride(0);
  156.     for i in 0..frame.height() {
  157.         file.write(&frame.data(0)[i as usize * wrap..][..wrap])
  158.             .unwrap();
  159.     }
  160.  
  161.     drop(file);
  162. }
  163.  
  164. fn process(
  165.     internal_buffer: *mut c_void,
  166.     internal_buffer_size: c_int,
  167.     internal_buffer_out: *mut c_void,
  168.     internal_buffer_out_size: c_int,
  169.     input: *mut c_void,
  170.     output: *mut c_void,
  171. ) -> Result<(), ffmpeg::Error> {
  172.     let mut read_format_context: *mut AVFormatContext =
  173.         unsafe { avformat_alloc_context() };
  174.     let read_io_context = unsafe {
  175.         avio_alloc_context(
  176.             internal_buffer as *mut c_uchar,
  177.             internal_buffer_size, // internal buffer and its size
  178.             0,                    // write flag (1=true, 0=false)
  179.             input, // user data, will be passed to our callback functions
  180.             Some(read),
  181.             None,
  182.             None,
  183.         )
  184.     };
  185.     unsafe {
  186.         (*read_format_context).pb = read_io_context;
  187.         (*read_format_context).flags |= AVFMT_FLAG_CUSTOM_IO;
  188.     }
  189.     unsafe {
  190.         avformat_open_input(
  191.             &mut read_format_context,
  192.             ptr::null_mut(),
  193.             ptr::null_mut(),
  194.             ptr::null_mut(),
  195.         );
  196.     }
  197.     let mut ictx = unsafe { Input::wrap(read_format_context) };
  198.     let input = ictx
  199.         .streams()
  200.         .best(Type::Video)
  201.         .ok_or(ffmpeg::Error::StreamNotFound)
  202.         .expect("stream not found");
  203.     let mut decoder =
  204.         ffmpeg::codec::context::Context::from_parameters(input.parameters())?
  205.             .decoder()
  206.             .video()?;
  207.  
  208.     let mut ofmt_ctx = ptr::null_mut();
  209.     let fmt = &CString::new("mp4").unwrap();
  210.     unsafe {
  211.         let ret = avformat_alloc_output_context2(
  212.             &mut ofmt_ctx,
  213.             ptr::null_mut(),
  214.             fmt.as_ptr(),
  215.             ptr::null(),
  216.         );
  217.         if ret != 0 {
  218.             panic!("can't allocate output context {ret}");
  219.         }
  220.         //     let encoder = avcodec_find_encoder(ffmpeg_sys_next::AVCodecID::AV_CODEC_ID_H264);
  221.         //     avformat_new_stream(*ofmt_ctx, encoder);
  222.     }
  223.     let out_stream = unsafe { avformat_new_stream(ofmt_ctx, ptr::null()) };
  224.     if out_stream.is_null() {
  225.         panic!("failed to allocate output stream");
  226.     }
  227.     let encoder = unsafe {
  228.         avcodec_find_encoder(ffmpeg_sys_next::AVCodecID::AV_CODEC_ID_H264)
  229.     };
  230.     if encoder.is_null() {
  231.         panic!("h264 encoder not found");
  232.     }
  233.  
  234.     let enc_ctx = unsafe { avcodec_alloc_context3(encoder) };
  235.     if enc_ctx.is_null() {
  236.         panic!("failed to allocate encoder context");
  237.     }
  238.  
  239.     unsafe {
  240.         (*enc_ctx).width = decoder.width() as i32;
  241.         (*enc_ctx).height = decoder.height() as i32;
  242.         (*enc_ctx).sample_aspect_ratio = decoder.aspect_ratio().into();
  243.         (*enc_ctx).pix_fmt = *(*encoder).pix_fmts;
  244.         (*enc_ctx).time_base = Rational::new(1001, 30000).into();
  245.         (*enc_ctx).framerate = Rational::new(30000, 1001).into();
  246.     }
  247.  
  248.     let ret = unsafe { avcodec_open2(enc_ctx, encoder, ptr::null_mut()) };
  249.     if ret < 0 {
  250.         panic!("failed to open video encoder for stream");
  251.     }
  252.     let ret = unsafe {
  253.         avcodec_parameters_from_context((*out_stream).codecpar, enc_ctx)
  254.     };
  255.     if ret != 0 {
  256.         panic!("error when creating parameters from context {ret}");
  257.     }
  258.     unsafe {
  259.         (*out_stream).time_base = (*enc_ctx).time_base;
  260.         (*out_stream).duration = input.duration();
  261.         (*out_stream).avg_frame_rate = Rational::new(30000, 1001).into();
  262.         (*out_stream)
  263.  
  264.     }
  265.  
  266.     let write_io_context = unsafe {
  267.         avio_alloc_context(
  268.             internal_buffer_out as *mut c_uchar,
  269.             internal_buffer_out_size, // internal buffer and its size
  270.             1,                        // write flag (1=true, 0=false)
  271.             output, // user data, will be passed to our callback functions
  272.             None,
  273.             Some(write),
  274.             Some(seek),
  275.         )
  276.     };
  277.  
  278.     unsafe {
  279.         (*ofmt_ctx).pb = write_io_context;
  280.         (*ofmt_ctx).flags |= AVFMT_FLAG_CUSTOM_IO;
  281.     }
  282.  
  283.     let ret = unsafe { avformat_write_header(ofmt_ctx, ptr::null_mut()) };
  284.     if ret < 0 {
  285.         panic!("error when writing header {ret}")
  286.     };
  287.     let video_stream_index = input.index();
  288.     let mut idx = 0;
  289.     //output.write_header()?;
  290.     for (stream, packet) in ictx.packets() {
  291.         if stream.index() == video_stream_index {
  292.             decoder.send_packet(&packet)?;
  293.             process_frames(&mut decoder, enc_ctx, ofmt_ctx, &mut idx)?;
  294.         }
  295.     }
  296.     decoder.send_eof()?;
  297.     let ret = unsafe { avcodec_send_frame(enc_ctx, ptr::null()) };
  298.     if ret < 0 {
  299.         panic!("can't flush encoder {ret}")
  300.     }
  301.     let mut encoded = Packet::empty();
  302.     let ret = unsafe { avcodec_receive_packet(enc_ctx, encoded.as_mut_ptr()) };
  303.     dbg!(ret);
  304.     let ret =
  305.         unsafe { av_interleaved_write_frame(ofmt_ctx, encoded.as_mut_ptr()) };
  306.     dbg!(ret);
  307.     let ret = unsafe { av_write_trailer(ofmt_ctx) };
  308.     dbg!(ret);
  309.     unsafe { avformat_free_context(ofmt_ctx) };
  310.     //encoder.send_eof()?;
  311.     Ok(())
  312. }
  313.  
  314. fn process_frames(
  315.     decoder: &mut decoder::Video,
  316.     encoder: *mut AVCodecContext,
  317.     //encoder: &mut encoder::video::Video,
  318.     output: *mut AVFormatContext,
  319.     // output: &mut Output,
  320.     idx: &mut usize,
  321. ) -> Result<(), ffmpeg::Error> {
  322.     let mut frame = Video::empty();
  323.     let mut i = 0;
  324.     loop {
  325.         dbg!(*idx);
  326.         match decoder.receive_frame(&mut frame) {
  327.             Ok(_) => {
  328.                 i += 1;
  329.                 pgm_save(&frame, &format!("frame-{idx}.pgm"));
  330.                 *idx += 1;
  331.                 let mut encoded = Packet::empty();
  332.                 let ret =
  333.                     unsafe { avcodec_send_frame(encoder, frame.as_ptr()) };
  334.                 if ret < 0 {
  335.                     panic!("error sending frame {ret}");
  336.                 }
  337.                 let ret = unsafe {
  338.                     avcodec_receive_packet(encoder, encoded.as_mut_ptr())
  339.                 };
  340.                 if ret == AVERROR(EAGAIN) || ret == AVERROR_EOF {
  341.                     break;
  342.                 }
  343.                 if ret < 0 {
  344.                     panic!("error sending packet {ret}");
  345.                 }
  346.                 let raw = encoded.as_mut_ptr();
  347.                 (unsafe { *raw }).duration = i;
  348.                 let ret = unsafe {
  349.                     av_interleaved_write_frame(output, encoded.as_mut_ptr())
  350.                 };
  351.                 if ret < 0 {
  352.                     panic!("error writing frame {ret}");
  353.                 }
  354.             }
  355.             Err(ffmpeg::Error::Eof) => {
  356.                 dbg!("eof");
  357.                 break;
  358.             }
  359.             Err(ffmpeg::Error::Other { errno: EAGAIN }) => {
  360.                 dbg!("again");
  361.                 break;
  362.             }
  363.             other => {
  364.                 dbg!(other);
  365.                 return other;
  366.             }
  367.         }
  368.     }
  369.     Ok(())
  370. }
  371.  
  372. trait SeekWrite: Seek + Write {}
  373. impl<T: Seek + Write> SeekWrite for T {}
  374.  
  375. fn main() {
  376.     let mut args = std::env::args().skip(1);
  377.     let input_filename = "out.mkv"; // args.next().unwrap();
  378.     let output_filename = "out.mp4"; // args.next().unwrap();
  379.     let input = std::fs::OpenOptions::new()
  380.         .read(true)
  381.         .open(input_filename)
  382.         .unwrap();
  383.     let output = std::fs::OpenOptions::new()
  384.         .write(true)
  385.         .create(true)
  386.         .open(output_filename)
  387.         .unwrap();
  388.     let buffer_size = MPEG_TS_PACKET_SIZE;
  389.     let internal_buffer_for_demux = unsafe { av_malloc(buffer_size) };
  390.     let internal_buffer_for_output = unsafe { av_malloc(1024) };
  391.     let inner: Box<dyn Read> = Box::new(input);
  392.     let input_ptr = Box::into_raw(Box::new(Wrapper { inner })) as *mut c_void;
  393.     let inner_: Box<dyn SeekWrite> = Box::new(output);
  394.     let output_ptr =
  395.         Box::into_raw(Box::new(Wrapper { inner: inner_ })) as *mut c_void;
  396.     process(
  397.         internal_buffer_for_demux,
  398.         buffer_size as i32,
  399.         internal_buffer_for_output,
  400.         1024 as i32,
  401.         input_ptr,
  402.         output_ptr,
  403.     )
  404.     .unwrap();
  405.     println!("done");
  406. }
  407.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement