Recherche avancée

Médias (0)

Mot : - Tags -/alertes

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

Autres articles (35)

  • MediaSPIP v0.2

    21 juin 2013, par

    MediaSPIP 0.2 est la première version de MediaSPIP stable.
    Sa date de sortie officielle est le 21 juin 2013 et est annoncée ici.
    Le fichier zip ici présent contient uniquement les sources de MediaSPIP en version standalone.
    Comme pour la version précédente, il est nécessaire d’installer manuellement l’ensemble des dépendances logicielles sur le serveur.
    Si vous souhaitez utiliser cette archive pour une installation en mode ferme, il vous faudra également procéder à d’autres modifications (...)

  • Mise à disposition des fichiers

    14 avril 2011, par

    Par défaut, lors de son initialisation, MediaSPIP ne permet pas aux visiteurs de télécharger les fichiers qu’ils soient originaux ou le résultat de leur transformation ou encodage. Il permet uniquement de les visualiser.
    Cependant, il est possible et facile d’autoriser les visiteurs à avoir accès à ces documents et ce sous différentes formes.
    Tout cela se passe dans la page de configuration du squelette. Il vous faut aller dans l’espace d’administration du canal, et choisir dans la navigation (...)

  • MediaSPIP version 0.1 Beta

    16 avril 2011, par

    MediaSPIP 0.1 beta est la première version de MediaSPIP décrétée comme "utilisable".
    Le fichier zip ici présent contient uniquement les sources de MediaSPIP en version standalone.
    Pour avoir une installation fonctionnelle, il est nécessaire d’installer manuellement l’ensemble des dépendances logicielles sur le serveur.
    Si vous souhaitez utiliser cette archive pour une installation en mode ferme, il vous faudra également procéder à d’autres modifications (...)

Sur d’autres sites (4946)

  • MJPEG decoding is 3x slower when opening a V4L2 input device [closed]

    26 octobre 2024, par Xenonic

    I'm trying to decode a MJPEG video stream coming from a webcam, but I'm hitting some performance blockers when using FFmpeg's C API in my application. I've recreated the problem using the example video decoder, where I just simply open the V4L2 input device, read packets, and push them to the decoder. What's strange is if I try to get my input packets from the V4L2 device instead of from a file, the avcodec_send_packet call to the decoder is nearly 3x slower. After further poking around, I narrowed the issue down to whether or not I open the V4L2 device at all.

    


    Let's look at a minimal example demonstrating this behavior :

    


    extern "C"&#xA;{&#xA;#include <libavcodec></libavcodec>avcodec.h>&#xA;#include <libavformat></libavformat>avformat.h>&#xA;#include <libavutil></libavutil>opt.h>&#xA;#include <libavdevice></libavdevice>avdevice.h>&#xA;}&#xA;&#xA;#define INBUF_SIZE 4096&#xA;&#xA;static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt)&#xA;{&#xA;    if (avcodec_send_packet(dec_ctx, pkt) &lt; 0)&#xA;        exit(1);&#xA; &#xA;    int ret = 0;&#xA;    while (ret >= 0) {&#xA;        ret = avcodec_receive_frame(dec_ctx, frame);&#xA;        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)&#xA;            return;&#xA;        else if (ret &lt; 0)&#xA;            exit(1);&#xA;&#xA;        // Here we&#x27;d save off the decoded frame, but that&#x27;s not necessary for the example.&#xA;    }&#xA;}&#xA;&#xA;int main(int argc, char **argv)&#xA;{&#xA;    const char *filename;&#xA;    const AVCodec *codec;&#xA;    AVCodecParserContext *parser;&#xA;    AVCodecContext *c= NULL;&#xA;    FILE *f;&#xA;    AVFrame *frame;&#xA;    uint8_t inbuf[INBUF_SIZE &#x2B; AV_INPUT_BUFFER_PADDING_SIZE];&#xA;    uint8_t *data;&#xA;    size_t   data_size;&#xA;    int ret;&#xA;    int eof;&#xA;    AVPacket *pkt;&#xA;&#xA;    filename = argv[1];&#xA;&#xA;    pkt = av_packet_alloc();&#xA;    if (!pkt)&#xA;        exit(1);&#xA;&#xA;    /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */&#xA;    memset(inbuf &#x2B; INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);&#xA;&#xA;    // Use MJPEG instead of the example&#x27;s MPEG1&#xA;    //codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);&#xA;    codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);&#xA;    if (!codec) {&#xA;        fprintf(stderr, "Codec not found\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    parser = av_parser_init(codec->id);&#xA;    if (!parser) {&#xA;        fprintf(stderr, "parser not found\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    c = avcodec_alloc_context3(codec);&#xA;    if (!c) {&#xA;        fprintf(stderr, "Could not allocate video codec context\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    if (avcodec_open2(c, codec, NULL) &lt; 0) {&#xA;        fprintf(stderr, "Could not open codec\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    c->pix_fmt = AV_PIX_FMT_YUVJ422P;&#xA;&#xA;    f = fopen(filename, "rb");&#xA;    if (!f) {&#xA;        fprintf(stderr, "Could not open %s\n", filename);&#xA;        exit(1);&#xA;    }&#xA;&#xA;    frame = av_frame_alloc();&#xA;    if (!frame) {&#xA;        fprintf(stderr, "Could not allocate video frame\n");&#xA;        exit(1);&#xA;    }&#xA;&#xA;    avdevice_register_all();&#xA;    auto* inputFormat = av_find_input_format("v4l2");&#xA;    AVDictionary* options = nullptr;&#xA;    av_dict_set(&amp;options, "input_format", "mjpeg", 0);&#xA;    av_dict_set(&amp;options, "video_size", "1920x1080", 0);&#xA;&#xA;    AVFormatContext* fmtCtx = nullptr;&#xA;&#xA;&#xA;    // Commenting this line out results in fast encoding!&#xA;    // Notice how fmtCtx is not even used anywhere, we still read packets from the file&#xA;    avformat_open_input(&amp;fmtCtx, "/dev/video0", inputFormat, &amp;options);&#xA;&#xA;&#xA;    // Just parse packets from a file and send them to the decoder.&#xA;    do {&#xA;        data_size = fread(inbuf, 1, INBUF_SIZE, f);&#xA;        if (ferror(f))&#xA;            break;&#xA;        eof = !data_size;&#xA;&#xA;        data = inbuf;&#xA;        while (data_size > 0 || eof) {&#xA;            ret = av_parser_parse2(parser, c, &amp;pkt->data, &amp;pkt->size,&#xA;                                   data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);&#xA;            if (ret &lt; 0) {&#xA;                fprintf(stderr, "Error while parsing\n");&#xA;                exit(1);&#xA;            }&#xA;            data      &#x2B;= ret;&#xA;            data_size -= ret;&#xA;&#xA;            if (pkt->size)&#xA;                decode(c, frame, pkt);&#xA;            else if (eof)&#xA;                break;&#xA;        }&#xA;    } while (!eof);&#xA;&#xA;    return 0;&#xA;}&#xA;

    &#xA;

    Here's a histogram of the CPU time spent in that avcodec_send_packet function call with and without opening the device by commenting out that avformat_open_input call above.

    &#xA;

    Without opening the V4L2 device :

    &#xA;

    fread_cpu

    &#xA;

    With opening the V4L2 device :

    &#xA;

    webcam_cpu

    &#xA;

    Interestingly we can see a significant number of function calls are in that 25ms time bin ! But most of them are 78ms... why ?

    &#xA;

    So what's going on here ? Why does opening the device destroy my decode performance ?

    &#xA;

    Additionally, if I try and run a seemingly equivalent pipeline through the ffmpeg tool itself, I don't hit this problem. Running this command :

    &#xA;

    ffmpeg -f v4l2 -input_format mjpeg -video_size 1920x1080 -r 30 -c:v mjpeg -i /dev/video0 -c:v copy out.mjpeg&#xA;

    &#xA;

    Is generating an output file with a reported speed of just barely over 1.0x, aka. 30 FPS. Perfect, why doesn't the C API give me the same results ? One thing to note is I do get periodic errors from the MJPEG decoder (about every second), not sure if these are a concern or not :

    &#xA;

    [mjpeg @ 0x5590d6b7b0] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 27 >= 27&#xA;[mjpeg @ 0x5590d6b7b0] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 30 >= 30&#xA;...&#xA;

    &#xA;

    I'm running on a Raspberry Pi CM4 with FFmpeg 6.1.1

    &#xA;

  • aaccoder : Implement Perceptual Noise Substitution for AAC

    15 avril 2015, par Rostislav Pehlivanov
    aaccoder : Implement Perceptual Noise Substitution for AAC
    

    This commit implements the perceptual noise substitution AAC extension. This is a proof of concept
    implementation, and as such, is not enabled by default. This is the fourth revision of this patch,
    made after some problems were noted out. Any changes made since the previous revisions have been indicated.

    In order to extend the encoder to use an additional codebook, the array holding each codebook has been
    modified with two additional entries - 13 for the NOISE_BT codebook and 12 which has a placeholder function.
    The cost system was modified to skip the 12th entry using an array to map the input and outputs it has. It
    also does not accept using the 13th codebook for any band which is not marked as containing noise, thereby
    restricting its ability to arbitrarily choose it for bands. The use of arrays allows the system to be easily
    extended to allow for intensity stereo encoding, which uses additional codebooks.

    The 12th entry in the codebook function array points to a function which stops the execution of the program
    by calling an assert with an always ’false’ argument. It was pointed out in an email discussion with
    Claudio Freire that having a ’NULL’ entry can result in unexpected behaviour and could be used as
    a security hole. There is no danger of this function being called during encoding due to the codebook maps introduced.

    Another change from version 1 of the patch is the addition of an argument to the encoder, ’-aac_pns’ to
    enable and disable the PNS. This currently defaults to disable the PNS, as it is experimental.
    The switch will be removed in the future, when the algorithm to select noise bands has been improved.
    The current algorithm simply compares the energy to the threshold (multiplied by a constant) to determine
    noise, however the FFPsyBand structure contains other useful figures to determine which bands carry noise more accurately.

    Some of the sample files provided triggered an assertion when the parameter to tune the threshold was set to
    a value of ’2.2’. Claudio Freire reported the problem’s source could be in the range of the scalefactor
    indices for noise and advised to measure the minimal index and clip anything above the maximum allowed
    value. This has been implemented and all the files which used to trigger the asserion now encode without error.

    The third revision of the problem also removes unneded variabes and comparisons. All of them were
    redundant and were of little use for when the PNS implementation would be extended.

    The fourth revision moved the clipping of the noise scalefactors outside the second loop of the two-loop
    algorithm in order to prevent their redundant calculations. Also, freq_mult has been changed to a float
    variable due to the fact that rounding errors can prove to be a problem at low frequencies.
    Considerations were taken whether the entire expression could be evaluated inside the expression
    , but in the end it was decided that it would be for the best if just the type of the variable were
    to change. Claudio Freire reported the two problems. There is no change of functionality
    (except for low sampling frequencies) so the spectral demonstrations at the end of this commit’s message were not updated.

    Finally, the way energy values are converted to scalefactor indices has changed since the first commit,
    as per the suggestion of Claudio Freire. This may still have some drawbacks, but unlike the first commit
    it works without having redundant offsets and outputs what the decoder expects to have, in terms of the
    ranges of the scalefactor indices.

    Some spectral comparisons : https://trac.ffmpeg.org/attachment/wiki/Encode/AAC/Original.png (original),
    https://trac.ffmpeg.org/attachment/wiki/Encode/AAC/PNS_NO.png (encoded without PNS),
    https://trac.ffmpeg.org/attachment/wiki/Encode/AAC/PNS1.2.png (encoded with PNS, const = 1.2),
    https://trac.ffmpeg.org/attachment/wiki/Encode/AAC/Difference1.png (spectral difference).
    The constant is the value which multiplies the threshold when it gets compared to the energy, larger
    values means more noise will be substituded by PNS values. Example when const = 2.2 :
    https://trac.ffmpeg.org/attachment/wiki/Encode/AAC/PNS_2.2.png

    Reviewed-by : Claudio Freire <klaussfreire@gmail.com>
    Signed-off-by : Michael Niedermayer <michaelni@gmx.at>

    • [DH] libavcodec/aaccoder.c
    • [DH] libavcodec/aacenc.c
    • [DH] libavcodec/aacenc.h
  • 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.&#xA;The only problem is that the time_base of my stream is wrongly written to the file.&#xA;I can confirm that I set the timebase correctly for both the encoder as well as the stream.

    &#xA;

    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.

    &#xA;

    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

    &#xA;

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

    &#xA;

    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.

    &#xA;

    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

    &#xA;

    let mut ost = octx.add_stream(codec)?;&#xA;ost.set_time_base(Rational::new(1, FPS));&#xA;&#xA;ost.set_parameters(&amp;encoder);&#xA;encoder.set_time_base(Rational::new(1, FPS));&#xA;ost.set_parameters(&amp;opened_encoder);&#xA;

    &#xA;

    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.

    &#xA;

    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.

    &#xA;

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

    &#xA;

    abstract main function

    &#xA;

    fn main() {&#xA;    let output_file = "output.mp4";&#xA;    let x264_opts = parse_opts("preset=medium".to_string()).expect("invalid x264 options string");&#xA;&#xA;    ffmpeg_next::init().unwrap();&#xA;    let mut octx = format::output(output_file).unwrap();&#xA;&#xA;    let mut encoder = Encoder::new(&amp;mut octx, x264_opts).unwrap();&#xA;&#xA;    format::context::output::dump(&amp;octx, 0, Some(&amp;output_file));&#xA;    //This line somehow clears the streams time base&#xA;    octx.write_header().unwrap();&#xA;&#xA;    // Without this line, the next logs returns Rational(1/30) Rational(1/15360) indicating streams timebase is wrong. even thought I set it above&#xA;    // this line changes it back but only for the print but not the actual output. Because the faulty data is written into the header&#xA;    // octx.stream_mut(0)&#xA;    //     .unwrap()&#xA;    //     .set_time_base(Rational::new(1, FPS));&#xA;&#xA;    println!(&#xA;        "---------------- {:?} {:?}",&#xA;        encoder.encoder.time_base(),&#xA;        octx.stream(0).unwrap().time_base(),&#xA;    );&#xA;&#xA;    for frame_num in 0..100 {&#xA;        let mut frame = encoder.create_frame();&#xA;        frame.set_pts(Some(frame_num));&#xA;        encoder.add_frame(&amp;frame, &amp;mut octx);&#xA;    }&#xA;&#xA;    encoder.close(&amp;mut octx);&#xA;    octx.write_trailer().unwrap();&#xA;}&#xA;

    &#xA;

    Encoder struct containing the implementation logic

    &#xA;

    struct Encoder {&#xA;    encoder: encoder::Video,&#xA;}&#xA;&#xA;impl Encoder {&#xA;    fn new(&#xA;        octx: &amp;mut format::context::Output,&#xA;        x264_opts: Dictionary,&#xA;    ) -> Result {&#xA;        let set_header = octx&#xA;            .format()&#xA;            .flags()&#xA;            .contains(ffmpeg_next::format::flag::Flags::GLOBAL_HEADER);&#xA;&#xA;        let codec = encoder::find(codec::Id::H264);&#xA;        let mut ost = octx.add_stream(codec)?;&#xA;        ost.set_time_base(Rational::new(1, FPS));&#xA;&#xA;        let mut encoder = codec::context::Context::new_with_codec(&#xA;            encoder::find(codec::Id::H264)&#xA;                .ok_or(ffmpeg_next::Error::InvalidData)&#xA;                .unwrap(),&#xA;        )&#xA;        .encoder()&#xA;        .video()&#xA;        .unwrap();&#xA;        ost.set_parameters(&amp;encoder);&#xA;&#xA;        encoder.set_width(WIDTH);&#xA;        encoder.set_height(HEIGHT);&#xA;        encoder.set_aspect_ratio(WIDTH as f64 / HEIGHT as f64);&#xA;        encoder.set_format(util::format::Pixel::YUV420P);&#xA;        encoder.set_frame_rate(Some(Rational::new(FPS, 1)));&#xA;        encoder.set_time_base(Rational::new(1, FPS));&#xA;&#xA;        if set_header {&#xA;            encoder.set_flags(ffmpeg_next::codec::flag::Flags::GLOBAL_HEADER);&#xA;        }&#xA;&#xA;        let opened_encoder = encoder&#xA;            .open_with(x264_opts.to_owned())&#xA;            .expect("error opening x264 with supplied settings");&#xA;        ost.set_parameters(&amp;opened_encoder);&#xA;&#xA;        println!(&#xA;            "\nost time_base: {}; encoder time_base: {}; encoder frame_rate: {}\n",&#xA;            ost.time_base(),&#xA;            &amp;opened_encoder.time_base(),&#xA;            &amp;opened_encoder.frame_rate()&#xA;        );&#xA;&#xA;        Ok(Self {&#xA;            encoder: opened_encoder,&#xA;        })&#xA;    }&#xA;&#xA;    fn add_frame(&amp;mut self, frame: &amp;frame::Video, octx: &amp;mut format::context::Output) {&#xA;        self.encoder.send_frame(frame).unwrap();&#xA;        self.process_packets(octx);&#xA;    }&#xA;&#xA;    fn close(&amp;mut self, octx: &amp;mut format::context::Output) {&#xA;        self.encoder.send_eof().unwrap();&#xA;        self.process_packets(octx);&#xA;    }&#xA;&#xA;    fn process_packets(&amp;mut self, octx: &amp;mut format::context::Output) {&#xA;        let mut encoded = Packet::empty();&#xA;        while self.encoder.receive_packet(&amp;mut encoded).is_ok() {&#xA;            encoded.set_stream(0);&#xA;            encoded.write_interleaved(octx).unwrap();&#xA;        }&#xA;    }&#xA;&#xA;    fn create_frame(&amp;self) -> frame::Video {&#xA;        return frame::Video::new(&#xA;            self.encoder.format(),&#xA;            self.encoder.width(),&#xA;            self.encoder.height(),&#xA;        );&#xA;    }&#xA;}&#xA;

    &#xA;

    other util stuff

    &#xA;

    use ffmpeg_next::{&#xA;    codec::{self},&#xA;    encoder, format, frame, util, Dictionary, Packet, Rational,&#xA;};&#xA;&#xA;const FPS: i32 = 30;&#xA;const WIDTH: u32 = 720;&#xA;const HEIGHT: u32 = 1080;&#xA;&#xA;fn parse_opts&lt;&#x27;a>(s: String) -> Option> {&#xA;    let mut dict = Dictionary::new();&#xA;    for keyval in s.split_terminator(&#x27;,&#x27;) {&#xA;        let tokens: Vec&lt;&amp;str> = keyval.split(&#x27;=&#x27;).collect();&#xA;        match tokens[..] {&#xA;            [key, val] => dict.set(key, val),&#xA;            _ => return None,&#xA;        }&#xA;    }&#xA;    Some(dict)&#xA;}&#xA;

    &#xA;