Recherche avancée

Médias (2)

Mot : - Tags -/plugins

Autres articles (56)

  • Les autorisations surchargées par les plugins

    27 avril 2010, par

    Mediaspip core
    autoriser_auteur_modifier() afin que les visiteurs soient capables de modifier leurs informations sur la page d’auteurs

  • Multilang : améliorer l’interface pour les blocs multilingues

    18 février 2011, par

    Multilang est un plugin supplémentaire qui n’est pas activé par défaut lors de l’initialisation de MediaSPIP.
    Après son activation, une préconfiguration est mise en place automatiquement par MediaSPIP init permettant à la nouvelle fonctionnalité d’être automatiquement opérationnelle. Il n’est donc pas obligatoire de passer par une étape de configuration pour cela.

  • (Dés)Activation de fonctionnalités (plugins)

    18 février 2011, par

    Pour gérer l’ajout et la suppression de fonctionnalités supplémentaires (ou plugins), MediaSPIP utilise à partir de la version 0.2 SVP.
    SVP permet l’activation facile de plugins depuis l’espace de configuration de MediaSPIP.
    Pour y accéder, il suffit de se rendre dans l’espace de configuration puis de se rendre sur la page "Gestion des plugins".
    MediaSPIP est fourni par défaut avec l’ensemble des plugins dits "compatibles", ils ont été testés et intégrés afin de fonctionner parfaitement avec chaque (...)

Sur d’autres sites (7830)

  • Encode h264 to match existing stream

    6 juin 2013, par Diego Sánchez

    In short : I have to encode a tiny amount of video frames and stitch them in front of a much bigger h.264 stream without reencoding said stream.

    The details : I receive a multi GB transport stream containing a h.264 es and an audio es. Currently the h.264 streams are always generated using x264, and I can assume this will be the case in the future. Now I have to prepend some video frames to this stream, but am not allowed to decode/encode the whole stream ; which leaves me with the only option to find out the exact parameters I need to pass x264_encoder_open so both streams match.

    Currently what I'm doing is :

    1. Demux the original ts and extract h.264 NAL packets.
    2. When I find the first "user data unregistered" SEI packet, I parse it and find a bunch of x264 parameters.
    3. Use libavcodec to start decoding the video. That gives me the dimensions of the picture and the h264 profile and level in the AVCodecContext structure.
    4. Match all of that as best as I can in the x264_param_t structure.

    I can do some encoding with that, and the encoded video plays correctly up to the join point. When VLC is reaching the stitch point it starts throwing out the following sequence of messages and soon after stops playing :

    [h264 @ 0x7fe36cd75be0] decode_slice_header error
    [h264 @ 0x7fe36cd75be0] no frame!
    [h264 @ 0x7fe36ccc9080] Width/height changing with threads is not implemented. Update your Libav version to the newest one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented.

    which clearly shows that my encoded frames do not match the original ones. I've been browsing the source code and can't seem to find a way of doing this. What I have currently (besides not working), involves a lot of guesswork, so even if I could make it work with the handful of example files I have, I would be scared to deploy this in production servers.

    So the obvious question is : Is there a safe, formal way of doing this ?

    Thanks in Advance

  • Encode h264 to match existing stream

    6 juin 2013, par Diego Sánchez

    In short : I have to encode a tiny amount of video frames and stitch them in front of a much bigger h.264 stream without reencoding said stream.

    The details : I receive a multi GB transport stream containing a h.264 es and an audio es. Currently the h.264 streams are always generated using x264, and I can assume this will be the case in the future. Now I have to prepend some video frames to this stream, but am not allowed to decode/encode the whole stream ; which leaves me with the only option to find out the exact parameters I need to pass x264_encoder_open so both streams match.

    Currently what I'm doing is :

    1. Demux the original ts and extract h.264 NAL packets.
    2. When I find the first "user data unregistered" SEI packet, I parse it and find a bunch of x264 parameters.
    3. Use libavcodec to start decoding the video. That gives me the dimensions of the picture and the h264 profile and level in the AVCodecContext structure.
    4. Match all of that as best as I can in the x264_param_t structure.

    I can do some encoding with that, and the encoded video plays correctly up to the join point. When VLC is reaching the stitch point it starts throwing out the following sequence of messages and soon after stops playing :

    [h264 @ 0x7fe36cd75be0] decode_slice_header error
    [h264 @ 0x7fe36cd75be0] no frame!
    [h264 @ 0x7fe36ccc9080] Width/height changing with threads is not implemented. Update your Libav version to the newest one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented.

    which clearly shows that my encoded frames do not match the original ones. I've been browsing the source code and can't seem to find a way of doing this. What I have currently (besides not working), involves a lot of guesswork, so even if I could make it work with the handful of example files I have, I would be scared to deploy this in production servers.

    So the obvious question is : Is there a safe, formal way of doing this ?

    Thanks in Advance

  • AVIOContext custom stream playback glitches/corruption on UDP stream

    21 décembre 2017, par WLGfx

    I’ve written a general all round player (for Android OS) which plays file based streams as well as streams from network sources, and it all works good. File based streams I’ve got the seeking which works too.

    What it is I’m now struggling with is now I’m using AVIOContext to latch onto a UDP stream which saves the packet data partially in memory and then to transient storage. This is so I can pause live TV and also seek within it.

    However, after much faffing about, during playback (seeking is only partial at the moment), either the video frame rate will drop from 25FPS (will be deinterlaced on higher spec devices) down to between 17 and 19 frames per second, or, it will glitch and grey out.

    When I playback the record TS data from the file, it plays perfect, so the UDP buffering and writing out the overflow is sound. (This is currently not true now, only currently a minor issue)

    I’m at the point were I’ve spent a lot of time on this and I’m at a loss as to why I get either frame drops or glitches.

    The class def :

    #define PKT_SIZE (188)
    #define PKT_SIZE7 (PKT_SIZE * 7)

    #define UDP_QUEUE_SIZE (12000)
    #define UDP_THRESHOLD (100)

    #define FILE_QUEUE_PKTS (200000)

    #define AVIO_QUEUE_SIZE (24)
    #define AVIO_THRESHOLD (10)

    extern "C" {
    #include "libavformat/avio.h"
    };

    /*
    * PracticalSocket class as found here with examples:
    * http://cs.baylor.edu/~donahoo/practical/CSockets/practical/
    */

    #include "PracticalSocket.h"

    class FFIOBufferManager2 {

    public:

       AVIOContext *avioContext = nullptr;

       bool quit = false;

       char udp_buffer[UDP_QUEUE_SIZE][PKT_SIZE7];
       int udp_write_pos, udp_size; // by PKT_SIZE7
       char *get_udp_buffer(int index);
       int get_udp_buffer_size() { return udp_size; }

       int file_write_pos, file_size; // by PKT_SIZE7
       std::fstream file_out, file_in;
       std::mutex udp_mutex, file_mutex;
       std::thread udp_thread, file_thread;

       static void udp_thread_func(FFIOBufferManager2 *io, const char *ip, int port);
       static void file_thread_func(FFIOBufferManager2 *io, const char *dir);
       void udp_thread_run(const char *ip, int port);
       void file_thread_run();

       char avio_buffer[AVIO_QUEUE_SIZE * 7 * PKT_SIZE];
       int64_t avio_read_offset; // controlled by udp mutex (quickest)
       static int avio_read(void *ptr, uint8_t *buff, int buf_size);
       static int64_t avio_seek(void *ptr, int64_t pos, int whence);
       int avio_read_run(uint8_t *buf, int buf_size);
       int64_t avio_seek_run(int64_t pos, int whence);
       void write_udp_overflow();

       void start(const char *ip, int port, const char *dir);

       void get_size_and_pos(int64_t *size, int64_t *pos);

       ~FFIOBufferManager2();
    };

    The classes methods :

    #include
    #include "FFIOBufferManager2.h"

    #include "LOG.h"

    void FFIOBufferManager2::start(const char *ip, int port, const char *dir) {

       file_write_pos = 0;
       file_size = 0;

       udp_write_pos = 0;
       udp_size = 0;
       avio_read_offset = 0;

       file_thread = std::thread(&FFIOBufferManager2::file_thread_func, this, dir);
       udp_thread = std::thread(&FFIOBufferManager2::udp_thread_func, this, ip, port);

       LOGD("Initialising avioContext");

       avioContext = avio_alloc_context((uint8_t*)avio_buffer,
                                        AVIO_QUEUE_SIZE * PKT_SIZE7,
                                        0,
                                        this,
                                        avio_read,
                                        NULL,
                                        avio_seek);
    }

    void FFIOBufferManager2::udp_thread_func(FFIOBufferManager2 *io, const char *ip, int port) {

       LOGD("AVIO UDP thread started address %s port %d - %08X", ip, port, (uint)io);

       io->udp_thread_run(ip, port); // run inside class

       LOGD("AVIO UDP thread stopped");
    }

    void FFIOBufferManager2::udp_thread_run(const char *ip, int port) {

       std::string addr = ip;

       UDPSocket socket(addr, (uint16_t)port);
       socket.joinGroup(addr);

       LOGD("UDP loop starting");

       while (!quit) {

           if (socket.recv(get_udp_buffer(udp_write_pos), PKT_SIZE7) == PKT_SIZE7) {

               udp_mutex.lock();

               udp_write_pos = (udp_write_pos + 1) % UDP_QUEUE_SIZE;
               udp_size++;
               if (udp_size >= UDP_QUEUE_SIZE) udp_size--;
               else avio_read_offset += PKT_SIZE7;

               udp_mutex.unlock();
           }
       }
    }

    void FFIOBufferManager2::file_thread_func(FFIOBufferManager2 *io, const char *dir) {

       LOGD("AVIO FILE thread started");

       std::string file = dir;
       const char *tsfile_name = "/tsdata.ts";
       file += tsfile_name;

       LOGD("Deleting old file %s", file.c_str());

       remove(file.c_str());

       {
           fstream temp; // create the ts file
           temp.open(file.c_str());
           temp.close();
       }

       LOGD("Opening %s for read and write", file.c_str());

       io->file_out.open(file, fstream::out | fstream::binary);
       io->file_in.open(file, fstream::in | fstream::binary);

       io->file_thread_run(); // continue inside the class to lessen pointer use

       LOGD("AVIO FILE thread stopped");
    }

    void FFIOBufferManager2::file_thread_run() {

       LOGD("FILE thread run");

       if (!file_out.is_open() || !file_in.is_open()) {

           LOGE("TS data file, error opening...");
           quit = true;
           return;
       }

       int udp_threshold = UDP_QUEUE_SIZE - (UDP_THRESHOLD * 4);

       while (!quit) {

           if (udp_size >= udp_threshold) write_udp_overflow();
           else usleep(1000 * 1);
       }
    }

    void FFIOBufferManager2::write_udp_overflow() {

       file_mutex.lock();

       udp_mutex.lock();
       int udp_write_pos_current = udp_write_pos;
       int udp_size_current = udp_size;
       udp_mutex.unlock();

       int udp_index = udp_write_pos_current - udp_size_current;
       if (udp_index < 0) udp_index += UDP_QUEUE_SIZE;
       int written = 0;

       //file_out.seekp((int64_t)file_write_pos * PKT_SIZE7);

       while (written < UDP_THRESHOLD) {
           file_out.write(get_udp_buffer(udp_index), PKT_SIZE7);
           written++;
           udp_index = (udp_index + 1) % UDP_QUEUE_SIZE;

           file_write_pos++;
           if (file_write_pos >= FILE_QUEUE_PKTS) {
               file_write_pos = 0;
               file_out.seekp(0);
           }
           file_size++;
           if (file_size > FILE_QUEUE_PKTS) file_size = FILE_QUEUE_PKTS;
       }

       udp_mutex.lock();
       udp_size -= UDP_THRESHOLD; // we've written this amount out
       udp_mutex.unlock();

       //file_out.flush();

       file_mutex.unlock();

       //LOGD("Written UDP overflow at %d of %d blocks file size %d",
       //     udp_index, written, file_size);
    }

    char *FFIOBufferManager2::get_udp_buffer(int index) {
       if (index < 0 || index >= UDP_QUEUE_SIZE) return nullptr;
       return ((char*)udp_buffer + (index * PKT_SIZE7));
    }

    /*
    * The avio_read and avio_seek now work on either 188 byte alignment or
    * byte alignment for the benefit of ffmpeg - byte positioning at the moment
    *
    * The file_mutex allows for either a read or write operation at a time
    */

    int FFIOBufferManager2::avio_read(void *ptr, uint8_t *buff, int buf_size) {
       FFIOBufferManager2 *io = (FFIOBufferManager2*)ptr;
       return io->avio_read_run(buff, buf_size);
    }

    int64_t FFIOBufferManager2::avio_seek(void *ptr, int64_t pos, int whence) {
       FFIOBufferManager2 *io = (FFIOBufferManager2*)ptr;
       return io->avio_seek_run(pos, whence);
    }

    int FFIOBufferManager2::avio_read_run(uint8_t *buf, int buf_size) {

       file_mutex.lock();
       udp_mutex.lock();

       int64_t cur_udp_write_pos = (int64_t) udp_write_pos * PKT_SIZE7;
       int64_t cur_udp_size = (int64_t) udp_size * PKT_SIZE7;

       int64_t cur_file_write_pos = (int64_t) file_write_pos * PKT_SIZE7;
       int64_t cur_file_size = (int64_t) file_size * PKT_SIZE7;

       int64_t cur_avio_read_offset = avio_read_offset; // already int64_t (under the udp_mutex)

       udp_mutex.unlock();

       if (cur_avio_read_offset < (AVIO_THRESHOLD * 4) * PKT_SIZE7) {
           file_mutex.unlock();
           return 0;
       }

       int64_t udp_buffer_max = (int64_t) (UDP_QUEUE_SIZE * PKT_SIZE7);
       int64_t file_buffer_max = (int64_t) (FILE_QUEUE_PKTS * PKT_SIZE7);
       uint8_t *ptr_udp_buffer = (uint8_t*)udp_buffer;
       int cur_written = 0;

       int file_reads = 0, udp_reads = 0; // for debugging

       int64_t cur_file_offset = cur_file_write_pos - cur_udp_size - cur_avio_read_offset;
       while (cur_file_offset < 0) cur_file_offset += file_buffer_max;

       if (cur_file_offset >= 0) {
           file_in.seekg(cur_file_offset);

           while (//cur_avio_read_offset > 0
                  cur_avio_read_offset > cur_udp_size
                  && cur_written < buf_size) { // read from file first

               file_in.read(&avio_buffer[cur_written], PKT_SIZE); // get 1 or 188 byte/s

               cur_file_offset+=PKT_SIZE;
               if (cur_file_offset >= file_buffer_max) { // back to file beginning
                   cur_file_offset = 0;
                   file_in.seekg(0);
               }

               cur_avio_read_offset-=PKT_SIZE;

               cur_written+=PKT_SIZE;
               file_reads+=PKT_SIZE;
           }
       }

       int64_t cur_udp_offset = (cur_udp_write_pos - cur_avio_read_offset);
       if (cur_udp_offset < 0) cur_udp_offset += udp_buffer_max;

       while (cur_avio_read_offset > AVIO_THRESHOLD * PKT_SIZE7
               && cur_avio_read_offset <= cur_udp_size
               && cur_written < buf_size) { // read the rest from udp buffer

           buf[cur_written] = ptr_udp_buffer[cur_udp_offset]; // get byte

           cur_udp_offset = (cur_udp_offset + 1) % udp_buffer_max;
           if (cur_udp_offset == 0) LOGD("AVIO UDP BUFFER to start");

           cur_avio_read_offset--;

           cur_written++;
           udp_reads++;
       }

       udp_mutex.lock();
       avio_read_offset -= cur_written;
       udp_mutex.unlock();

       file_mutex.unlock();

       if (cur_written) {
           LOGD("AVIO_READ: Written %d of %d, avio_offset %lld, file reads %d, udp reads %d, udp offset %lld, file offset %lld, file size %lld",
                cur_written, buf_size,
                cur_avio_read_offset,
                file_reads, udp_reads,
                cur_udp_write_pos, cur_file_write_pos, cur_file_size);
       }

       return cur_written;
    }

    int64_t FFIOBufferManager2::avio_seek_run(int64_t pos, int whence) {
       // SEEK_SET(0), SEEK_CUR(1), SEEK_END(2), AVSEEK_SIZE

       int64_t new_pos = -1;
       int64_t full_length = (udp_size + file_size) * PKT_SIZE7;

       switch (whence) {

           case AVSEEK_SIZE:
               LOGD("AVSEEK_SIZE pos %lld", pos);
               break;

           case SEEK_SET:
               LOGD("AVSEEK_SET pos %lld", pos);
               if (pos > full_length) new_pos = full_length;
               else new_pos = full_length - pos;
               break;

           case SEEK_CUR:
               LOGD("AVSEEK_CUR pos %lld", pos);
               break;

           case SEEK_END:
               LOGD("AVSEEK_END pos %lld", pos);
               new_pos = pos;
               break;

           default:
               LOGD("UNKNOWN AVIO SEEK whence %d pos %lld", whence, pos);
               break;
       }

       if (new_pos >= 0) {

           udp_mutex.lock();

           new_pos = (new_pos / PKT_SIZE) * PKT_SIZE; // align to packet boundary
           avio_read_offset = new_pos;
           //file_out.seekg(full_length - new_pos);

           udp_mutex.unlock();

           return full_length - new_pos;
       }

       return -1;
    }

    FFIOBufferManager2::~FFIOBufferManager2() {
       if (avioContext) ;// TODO whoops
       quit = true;
       if (udp_thread.joinable()) udp_thread.join();
       if (file_thread.joinable()) file_thread.join();
    }

    void FFIOBufferManager2::get_size_and_pos(int64_t *size, int64_t *pos) {
       file_mutex.lock();
       udp_mutex.lock();

       *size = (udp_size + file_size) * PKT_SIZE7;
       *pos = *size - avio_read_offset;

       udp_mutex.unlock();
       file_mutex.unlock();
    }

    It’ll play for a few seconds before any of the glitches start to appear. I have checked against the udp_buffer and the avio_buffer, but my suspicions lie with one of two things :

    1. Reading and writing to the file.
    2. the avio_read method is wrong.

    Has anybody got any input as to why this is occurring ? Any thoughts would be greatly appreciated.

    If you need any more information I’ll be glad to provide more details.

    EDIT : Seeking now actually moves to any point within the stream, but now doesn’t read from the file recording. Although that’s only a minor issue at the moment.

    The main two issues still stand, frame rate drops dramatically and the glitches after approximately 8 seconds.