1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::ffi::{CStr, CString};

use libav_sys_ng::{
    self, av_dump_format, avformat_alloc_output_context2, avformat_free_context, AVFormatContext,
    AVInputFormat, AVOutputFormat,
};

pub struct FormatContext {
    _format_ctx: *mut libav_sys_ng::AVFormatContext,
}

impl FormatContext {
    pub fn new(
        format_name: &str,
        filename: &str,
        output_format: Option<AVOutputFormat>,
    ) -> Option<FormatContext> {
        unsafe {
            let mut context = core::ptr::null_mut::<libav_sys_ng::AVFormatContext>();

            let ptr = match output_format {
                Some(fmt) => &fmt,
                None => core::ptr::null::<AVOutputFormat>(),
            };

            let fmt_name = CString::new(format_name).expect("CString::new(format_name) failed");
            let real_filename = CString::new(filename).expect("CString::new(filename) failed");

            avformat_alloc_output_context2(
                &mut context,
                ptr,
                fmt_name.as_ptr(),
                real_filename.as_ptr(),
            );

            if context == core::ptr::null_mut() {
                return None;
            } else {
                return Some(FormatContext {
                    _format_ctx: context,
                });
            }
        }
    }

    pub unsafe fn get_input_format(&self) -> *const AVInputFormat {
        return (*self._format_ctx).iformat;
    }

    pub fn get_output_format(&self) -> &AVOutputFormat {
        unsafe {
            return &*(*self._format_ctx).oformat as &AVOutputFormat;
        }
    }

    pub unsafe fn raw(&mut self) -> *mut AVFormatContext {
        self._format_ctx
    }

    pub fn dump(&self, index: i32, url: &str, is_output: bool) {
        unsafe {
            let raw_url = CString::new(url).expect("CString::new(url) failed");

            av_dump_format(self._format_ctx, index, raw_url.as_ptr(), is_output as i32)
        }
    }
}

impl Drop for FormatContext {
    fn drop(&mut self) {
        unsafe {
            avformat_free_context(self._format_ctx);
        }
    }
}