Recherche avancée

Médias (0)

Mot : - Tags -/alertes

Aucun média correspondant à vos critères n’est disponible sur le site.

Autres articles (4)

  • Support de tous types de médias

    10 avril 2011

    Contrairement à beaucoup de logiciels et autres plate-formes modernes de partage de documents, MediaSPIP a l’ambition de gérer un maximum de formats de documents différents qu’ils soient de type : images (png, gif, jpg, bmp et autres...) ; audio (MP3, Ogg, Wav et autres...) ; vidéo (Avi, MP4, Ogv, mpg, mov, wmv et autres...) ; contenu textuel, code ou autres (open office, microsoft office (tableur, présentation), web (html, css), LaTeX, Google Earth) (...)

  • Supporting all media types

    13 avril 2011, par

    Unlike most software and media-sharing platforms, MediaSPIP aims to manage as many different media types as possible. The following are just a few examples from an ever-expanding list of supported formats : images : png, gif, jpg, bmp and more audio : MP3, Ogg, Wav and more video : AVI, MP4, OGV, mpg, mov, wmv and more text, code and other data : OpenOffice, Microsoft Office (Word, PowerPoint, Excel), web (html, CSS), LaTeX, Google Earth and (...)

  • MediaSPIP Init et Diogène : types de publications de MediaSPIP

    11 novembre 2010, par

    À l’installation d’un site MediaSPIP, le plugin MediaSPIP Init réalise certaines opérations dont la principale consiste à créer quatre rubriques principales dans le site et de créer cinq templates de formulaire pour Diogène.
    Ces quatre rubriques principales (aussi appelées secteurs) sont : Medias ; Sites ; Editos ; Actualités ;
    Pour chacune de ces rubriques est créé un template de formulaire spécifique éponyme. Pour la rubrique "Medias" un second template "catégorie" est créé permettant d’ajouter (...)

Sur d’autres sites (3551)

  • ffmpeg-next potential bug in write_header causes timebase to bet set to Rational(1/15360)

    7 septembre 2024, par Huhngut

    I am trying to encode a video using the ffmpeg_next crate. I got everything working and it successfully creates an output video.
The only problem is that the time_base of my stream is wrongly written to the file.
I can confirm that I set the timebase correctly for both the encoder as well as the stream.

    


    By debug prints I was able to narrow the problem down. octx.write_header().unwrap(); causes the stream timebase to be reset from Rational(1/30) to Rational(1/15360). Changing the timebase back afterwards has no effect. The wrong value must have been written to the header.

    


    I modified the src code of ffmpeg-next and recompiled it. I can confirm that the correct value is set before the call to avformat_write_header

    


    pub fn write_header(&mut self) -> Result<(), Error> {
        println!(
            "_________________ {:?}",
            self.stream(0).unwrap().time_base()
        );
        unsafe {
            match avformat_write_header(self.as_mut_ptr(), ptr::null_mut()) {
                0 => Ok(()),
                e => Err(Error::from(e)),
            }
        }
    }


    


    To my understanding this must be a bug in the crate but I dont want to accuse someone with my non existing knowledge about ffmpeg. Also the examples in the github repo seem not to have this problem. My fault then ? Unfortunately I was not able to get the transcode-x264 to run. Most of my code comes from this example.

    


    Relevant code bits are these. I dont know how much the set_parameters influences anything. My testing said it has no influence. I also tried to set the timebase at the very end of the function if it gets reset my the parameters. This is not working

    


    let mut ost = octx.add_stream(codec)?;
ost.set_time_base(Rational::new(1, FPS));

ost.set_parameters(&encoder);
encoder.set_time_base(Rational::new(1, FPS));
ost.set_parameters(&opened_encoder);


    


    By default and in the above example the streams timebase is 0/0. If I leave it out or change it to this manually it has no effect.

    


    I also noticed that changing the value inside set_pts influences the output fps. Although not the timebase. I think this is more of a sideeffect.

    


    I will leave a minimal reproducible example below. Any help or hints would be appreciated

    


    abstract main function

    


    fn main() {
    let output_file = "output.mp4";
    let x264_opts = parse_opts("preset=medium".to_string()).expect("invalid x264 options string");

    ffmpeg_next::init().unwrap();
    let mut octx = format::output(output_file).unwrap();

    let mut encoder = Encoder::new(&mut octx, x264_opts).unwrap();

    format::context::output::dump(&octx, 0, Some(&output_file));
    //This line somehow clears the streams time base
    octx.write_header().unwrap();

    // Without this line, the next logs returns Rational(1/30) Rational(1/15360) indicating streams timebase is wrong. even thought I set it above
    // this line changes it back but only for the print but not the actual output. Because the faulty data is written into the header
    // octx.stream_mut(0)
    //     .unwrap()
    //     .set_time_base(Rational::new(1, FPS));

    println!(
        "---------------- {:?} {:?}",
        encoder.encoder.time_base(),
        octx.stream(0).unwrap().time_base(),
    );

    for frame_num in 0..100 {
        let mut frame = encoder.create_frame();
        frame.set_pts(Some(frame_num));
        encoder.add_frame(&frame, &mut octx);
    }

    encoder.close(&mut octx);
    octx.write_trailer().unwrap();
}


    


    Encoder struct containing the implementation logic

    


    struct Encoder {
    encoder: encoder::Video,
}

impl Encoder {
    fn new(
        octx: &mut format::context::Output,
        x264_opts: Dictionary,
    ) -> Result {
        let set_header = octx
            .format()
            .flags()
            .contains(ffmpeg_next::format::flag::Flags::GLOBAL_HEADER);

        let codec = encoder::find(codec::Id::H264);
        let mut ost = octx.add_stream(codec)?;
        ost.set_time_base(Rational::new(1, FPS));

        let mut encoder = codec::context::Context::new_with_codec(
            encoder::find(codec::Id::H264)
                .ok_or(ffmpeg_next::Error::InvalidData)
                .unwrap(),
        )
        .encoder()
        .video()
        .unwrap();
        ost.set_parameters(&encoder);

        encoder.set_width(WIDTH);
        encoder.set_height(HEIGHT);
        encoder.set_aspect_ratio(WIDTH as f64 / HEIGHT as f64);
        encoder.set_format(util::format::Pixel::YUV420P);
        encoder.set_frame_rate(Some(Rational::new(FPS, 1)));
        encoder.set_time_base(Rational::new(1, FPS));

        if set_header {
            encoder.set_flags(ffmpeg_next::codec::flag::Flags::GLOBAL_HEADER);
        }

        let opened_encoder = encoder
            .open_with(x264_opts.to_owned())
            .expect("error opening x264 with supplied settings");
        ost.set_parameters(&opened_encoder);

        println!(
            "\nost time_base: {}; encoder time_base: {}; encoder frame_rate: {}\n",
            ost.time_base(),
            &opened_encoder.time_base(),
            &opened_encoder.frame_rate()
        );

        Ok(Self {
            encoder: opened_encoder,
        })
    }

    fn add_frame(&mut self, frame: &frame::Video, octx: &mut format::context::Output) {
        self.encoder.send_frame(frame).unwrap();
        self.process_packets(octx);
    }

    fn close(&mut self, octx: &mut format::context::Output) {
        self.encoder.send_eof().unwrap();
        self.process_packets(octx);
    }

    fn process_packets(&mut self, octx: &mut format::context::Output) {
        let mut encoded = Packet::empty();
        while self.encoder.receive_packet(&mut encoded).is_ok() {
            encoded.set_stream(0);
            encoded.write_interleaved(octx).unwrap();
        }
    }

    fn create_frame(&self) -> frame::Video {
        return frame::Video::new(
            self.encoder.format(),
            self.encoder.width(),
            self.encoder.height(),
        );
    }
}


    


    other util stuff

    


    use ffmpeg_next::{
    codec::{self},
    encoder, format, frame, util, Dictionary, Packet, Rational,
};

const FPS: i32 = 30;
const WIDTH: u32 = 720;
const HEIGHT: u32 = 1080;

fn parse_opts<'a>(s: String) -> Option> {
    let mut dict = Dictionary::new();
    for keyval in s.split_terminator(',') {
        let tokens: Vec<&str> = keyval.split('=').collect();
        match tokens[..] {
            [key, val] => dict.set(key, val),
            _ => return None,
        }
    }
    Some(dict)
}


    


  • Revision 32594 : plugins en minuscules, et alias pour les noms de sites

    1er novembre 2009, par fil@… — Log

    plugins en minuscules, et alias pour les noms de sites