Recherche avancée

Médias (91)

Autres articles (52)

  • Support audio et vidéo HTML5

    10 avril 2011

    MediaSPIP utilise les balises HTML5 video et audio pour la lecture de documents multimedia en profitant des dernières innovations du W3C supportées par les navigateurs modernes.
    Pour les navigateurs plus anciens, le lecteur flash Flowplayer est utilisé.
    Le lecteur HTML5 utilisé a été spécifiquement créé pour MediaSPIP : il est complètement modifiable graphiquement pour correspondre à un thème choisi.
    Ces technologies permettent de distribuer vidéo et son à la fois sur des ordinateurs conventionnels (...)

  • Librairies et logiciels spécifiques aux médias

    10 décembre 2010, par

    Pour un fonctionnement correct et optimal, plusieurs choses sont à prendre en considération.
    Il est important, après avoir installé apache2, mysql et php5, d’installer d’autres logiciels nécessaires dont les installations sont décrites dans les liens afférants. Un ensemble de librairies multimedias (x264, libtheora, libvpx) utilisées pour l’encodage et le décodage des vidéos et sons afin de supporter le plus grand nombre de fichiers possibles. Cf. : ce tutoriel ; FFMpeg avec le maximum de décodeurs et (...)

  • Gestion générale des documents

    13 mai 2011, par

    MédiaSPIP ne modifie jamais le document original mis en ligne.
    Pour chaque document mis en ligne il effectue deux opérations successives : la création d’une version supplémentaire qui peut être facilement consultée en ligne tout en laissant l’original téléchargeable dans le cas où le document original ne peut être lu dans un navigateur Internet ; la récupération des métadonnées du document original pour illustrer textuellement le fichier ;
    Les tableaux ci-dessous expliquent ce que peut faire MédiaSPIP (...)

Sur d’autres sites (4040)

  • sws_scale performance comparison to media players real time resize

    14 juillet 2018, par Andrey Katkov

    While playing 4K video user can resize players window - and result image will be scaled smoothly in run time.

    On the other hand - program written with libav which reads 4k video file frame by frame and scale it down with sws_scale function do it less effective : it took more time then video duration to resize it.

    Why is it so ? Maybe because player fps is less and some frames are skipped - but video still looks smooth ?

  • javax.media.NoDataSinkException

    23 novembre 2022, par Divya

    I am trying to convert Jpeg images into .mov video file

    



     package com.ecomm.pl4mms.test;&#xA;&#xA;import java.io.*;&#xA;import java.util.*;&#xA;import java.awt.Dimension;&#xA;&#xA;import javax.media.*;&#xA;import javax.media.control.*;&#xA;import javax.media.protocol.*;&#xA;import javax.media.protocol.DataSource;&#xA;import javax.media.datasink.*;&#xA;import javax.media.format.VideoFormat;&#xA;import javax.media.format.JPEGFormat;&#xA;&#xA;public class JpegImagesToMovie implements ControllerListener, DataSinkListener {&#xA;&#xA;    public boolean doItPath(int width, int height, int frameRate, Vector inFiles, String outputURL) {&#xA;        // Check for output file extension.&#xA;        if (!outputURL.endsWith(".mov") &amp;&amp; !outputURL.endsWith(".MOV")) {&#xA;            // System.err.println("The output file extension should end with a&#xA;            // .mov extension");&#xA;            prUsage();&#xA;        }&#xA;&#xA;        // Generate the output media locators.&#xA;        MediaLocator oml;&#xA;&#xA;        if ((oml = createMediaLocator("file:" &#x2B; outputURL)) == null) {&#xA;            // System.err.println("Cannot build media locator from: " &#x2B;&#xA;            // outputURL);&#xA;            //System.exit(0);&#xA;        }&#xA;&#xA;        boolean success = doIt(width, height, frameRate, inFiles, oml);&#xA;&#xA;        System.gc();&#xA;        return success;&#xA;    }&#xA;&#xA;    public boolean doIt(int width, int height, int frameRate, Vector inFiles, MediaLocator outML) {&#xA;        try {&#xA;            System.out.println(inFiles.size());&#xA;            ImageDataSource ids = new ImageDataSource(width, height, frameRate, inFiles);&#xA;&#xA;            Processor p;&#xA;&#xA;            try {&#xA;                // System.err.println("- create processor for the image&#xA;                // datasource ...");&#xA;                System.out.println("processor");&#xA;                p = Manager.createProcessor(ids);&#xA;                System.out.println("success");&#xA;            } catch (Exception e) {&#xA;                // System.err.println("Yikes! Cannot create a processor from the&#xA;                // data source.");&#xA;                return false;&#xA;            }&#xA;&#xA;            p.addControllerListener(this);&#xA;&#xA;            // Put the Processor into configured state so we can set&#xA;            // some processing options on the processor.&#xA;            p.configure();&#xA;            if (!waitForState(p, p.Configured)) {&#xA;                System.out.println("Issue configuring");&#xA;                // System.err.println("Failed to configure the processor.");&#xA;                p.close();&#xA;                p.deallocate();&#xA;                return false;&#xA;            }&#xA;            System.out.println("Configured");&#xA;&#xA;            // Set the output content descriptor to QuickTime.&#xA;            p.setContentDescriptor(new ContentDescriptor(FileTypeDescriptor.QUICKTIME));&#xA;System.out.println(outML);&#xA;            // Query for the processor for supported formats.&#xA;            // Then set it on the processor.&#xA;            TrackControl tcs[] = p.getTrackControls();&#xA;            Format f[] = tcs[0].getSupportedFormats();&#xA;            System.out.println(f[0].getEncoding());&#xA;            if (f == null || f.length &lt;= 0) {&#xA;                 System.err.println("The mux does not support the input format: " &#x2B; tcs[0].getFormat());&#xA;                p.close();&#xA;                p.deallocate();&#xA;                return false;&#xA;            }&#xA;&#xA;            tcs[0].setFormat(f[0]);&#xA;&#xA;            // System.err.println("Setting the track format to: " &#x2B; f[0]);&#xA;&#xA;            // We are done with programming the processor. Let&#x27;s just&#xA;            // realize it.&#xA;            p.realize();&#xA;            if (!waitForState(p, p.Realized)) {&#xA;                // System.err.println("Failed to realize the processor.");&#xA;                p.close();&#xA;                p.deallocate();&#xA;                return false;&#xA;            }&#xA;&#xA;            // Now, we&#x27;ll need to create a DataSink.&#xA;            DataSink dsink;&#xA;            if ((dsink = createDataSink(p, outML)) == null) {&#xA;                // System.err.println("Failed to create a DataSink for the given&#xA;                // output MediaLocator: " &#x2B; outML);&#xA;                p.close();&#xA;                p.deallocate();&#xA;                return false;&#xA;            }&#xA;&#xA;            dsink.addDataSinkListener(this);&#xA;            fileDone = false;&#xA;&#xA;            // System.err.println("start processing...");&#xA;&#xA;            // OK, we can now start the actual transcoding.&#xA;            try {&#xA;                p.start();&#xA;                dsink.start();&#xA;            } catch (IOException e) {&#xA;                p.close();&#xA;                p.deallocate();&#xA;                dsink.close();&#xA;                // System.err.println("IO error during processing");&#xA;                return false;&#xA;            }&#xA;&#xA;            // Wait for EndOfStream event.&#xA;            waitForFileDone();&#xA;&#xA;            // Cleanup.&#xA;            try {&#xA;                dsink.close();&#xA;            } catch (Exception e) {&#xA;            }&#xA;            p.removeControllerListener(this);&#xA;&#xA;            // System.err.println("...done processing.");&#xA;&#xA;            p.close();&#xA;&#xA;            return true;&#xA;        } catch (NotConfiguredError e) {&#xA;            // TODO Auto-generated catch block&#xA;            e.printStackTrace();&#xA;        }&#xA;&#xA;        return false;&#xA;    }&#xA;&#xA;    /**&#xA;     * Create the DataSink.&#xA;     */&#xA;    DataSink createDataSink(Processor p, MediaLocator outML) {&#xA;System.out.println("In data sink");&#xA;        DataSource ds;&#xA;&#xA;        if ((ds = p.getDataOutput()) == null) {&#xA;         System.out.println("Something is really wrong: the processor does not have an output DataSource");&#xA;            return null;&#xA;        }&#xA;&#xA;        DataSink dsink;&#xA;&#xA;        try {&#xA;             System.out.println("- create DataSink for: " &#x2B; ds.toString()&#x2B;ds.getContentType());&#xA;            dsink = Manager.createDataSink(ds, outML);&#xA;            dsink.open();&#xA;            System.out.println("Done data sink");&#xA;        } catch (Exception e) {&#xA;             System.err.println("Cannot create the DataSink: " &#x2B;e);&#xA;             e.printStackTrace();&#xA;            return null;&#xA;        }&#xA;&#xA;        return dsink;&#xA;    }&#xA;&#xA;    Object waitSync = new Object();&#xA;    boolean stateTransitionOK = true;&#xA;&#xA;    /**&#xA;     * Block until the processor has transitioned to the given state. Return&#xA;     * false if the transition failed.&#xA;     */&#xA;    boolean waitForState(Processor p, int state) {&#xA;        synchronized (waitSync) {&#xA;            try {&#xA;                while (p.getState() &lt; state &amp;&amp; stateTransitionOK)&#xA;                    waitSync.wait();&#xA;            } catch (Exception e) {&#xA;            }&#xA;        }&#xA;        return stateTransitionOK;&#xA;    }&#xA;&#xA;    /**&#xA;     * Controller Listener.&#xA;     */&#xA;    public void controllerUpdate(ControllerEvent evt) {&#xA;&#xA;        if (evt instanceof ConfigureCompleteEvent || evt instanceof RealizeCompleteEvent&#xA;                || evt instanceof PrefetchCompleteEvent) {&#xA;            synchronized (waitSync) {&#xA;                stateTransitionOK = true;&#xA;                waitSync.notifyAll();&#xA;            }&#xA;        } else if (evt instanceof ResourceUnavailableEvent) {&#xA;            synchronized (waitSync) {&#xA;                stateTransitionOK = false;&#xA;                waitSync.notifyAll();&#xA;            }&#xA;        } else if (evt instanceof EndOfMediaEvent) {&#xA;            evt.getSourceController().stop();&#xA;            evt.getSourceController().close();&#xA;        }&#xA;    }&#xA;&#xA;    Object waitFileSync = new Object();&#xA;    boolean fileDone = false;&#xA;    boolean fileSuccess = true;&#xA;&#xA;    /**&#xA;     * Block until file writing is done.&#xA;     */&#xA;    boolean waitForFileDone() {&#xA;        synchronized (waitFileSync) {&#xA;            try {&#xA;                while (!fileDone)&#xA;                    waitFileSync.wait();&#xA;            } catch (Exception e) {&#xA;            }&#xA;        }&#xA;        return fileSuccess;&#xA;    }&#xA;&#xA;    /**&#xA;     * Event handler for the file writer.&#xA;     */&#xA;    public void dataSinkUpdate(DataSinkEvent evt) {&#xA;&#xA;        if (evt instanceof EndOfStreamEvent) {&#xA;            synchronized (waitFileSync) {&#xA;                fileDone = true;&#xA;                waitFileSync.notifyAll();&#xA;            }&#xA;        } else if (evt instanceof DataSinkErrorEvent) {&#xA;            synchronized (waitFileSync) {&#xA;                fileDone = true;&#xA;                fileSuccess = false;&#xA;                waitFileSync.notifyAll();&#xA;            }&#xA;        }&#xA;    }&#xA;&#xA;    public static void main(String arg[]) {&#xA;        try {&#xA;            String args[] = { "-w 100 -h 100 -f 100 -o F:\\test.mov F:\\Text69.jpg F:\\Textnew.jpg" };&#xA;            if (args.length == 0)&#xA;                prUsage();&#xA;&#xA;            // Parse the arguments.&#xA;            int i = 0;&#xA;            int width = -1, height = -1, frameRate = 1;&#xA;            Vector inputFiles = new Vector();&#xA;            String outputURL = null;&#xA;&#xA;            while (i &lt; args.length) {&#xA;&#xA;                if (args[i].equals("-w")) {&#xA;                    i&#x2B;&#x2B;;&#xA;                    if (i >= args.length)&#xA;                        width = new Integer(args[i]).intValue();&#xA;                } else if (args[i].equals("-h")) {&#xA;                    i&#x2B;&#x2B;;&#xA;                    if (i >= args.length)&#xA;                        height = new Integer(args[i]).intValue();&#xA;                } else if (args[i].equals("-f")) {&#xA;                    i&#x2B;&#x2B;;&#xA;                    if (i >= args.length)&#xA;                        frameRate = new Integer(args[i]).intValue();&#xA;                } else if (args[i].equals("-o")) {&#xA;                    System.out.println("in ou");&#xA;                    i&#x2B;&#x2B;;&#xA;                    System.out.println(i);&#xA;                    if (i >= args.length)&#xA;                        outputURL = args[i];&#xA;                    System.out.println(outputURL);&#xA;                } else {&#xA;                    System.out.println("adding"&#x2B;args[i]);&#xA;                    inputFiles.addElement(args[i]);&#xA;                }&#xA;                i&#x2B;&#x2B;;&#xA;&#xA;            }&#xA;            inputFiles.addElement("F:\\Textnew.jpg");&#xA;            outputURL = "F:\\test.mov";&#xA;            System.out.println(inputFiles.size() &#x2B; outputURL);&#xA;            if (outputURL == null || inputFiles.size() == 0)&#xA;                prUsage();&#xA;&#xA;            // Check for output file extension.&#xA;            if (!outputURL.endsWith(".mov") &amp;&amp; !outputURL.endsWith(".MOV")) {&#xA;                System.err.println("The output file extension should end with a .mov extension");&#xA;                prUsage();&#xA;            }&#xA;            width = 100;&#xA;            height = 100;&#xA;            if (width &lt; 0 || height &lt; 0) {&#xA;                System.err.println("Please specify the correct image size.");&#xA;                prUsage();&#xA;            }&#xA;&#xA;            // Check the frame rate.&#xA;            if (frameRate &lt; 1)&#xA;                frameRate = 1;&#xA;&#xA;            // Generate the output media locators.&#xA;            MediaLocator oml;&#xA;            oml = createMediaLocator(outputURL);&#xA;            System.out.println("Media" &#x2B; oml);&#xA;            if (oml == null) {&#xA;                System.err.println("Cannot build media locator from: " &#x2B; outputURL);&#xA;                // //System.exit(0);&#xA;            }&#xA;            System.out.println("Before change");&#xA;System.out.println(inputFiles.size());&#xA;            JpegImagesToMovie imageToMovie = new JpegImagesToMovie();&#xA;            boolean status = imageToMovie.doIt(width, height, frameRate, inputFiles, oml);&#xA;            System.out.println("Status"&#x2B;status);&#xA;            //System.exit(0);&#xA;        } catch (Exception e) {&#xA;            // TODO Auto-generated catch block&#xA;            e.printStackTrace();&#xA;        }&#xA;    }&#xA;&#xA;    static void prUsage() {&#xA;        System.err.println(&#xA;                "Usage: java JpegImagesToMovie -w <width> -h <height> -f  -o <output url="url"> <input jpeg="jpeg" file="file" 1="1" /> <input jpeg="jpeg" file="file" 2="2" /> ...");&#xA;        //System.exit(-1);&#xA;    }&#xA;&#xA;    /**&#xA;     * Create a media locator from the given string.&#xA;     */&#xA;    static MediaLocator createMediaLocator(String url) {&#xA;        System.out.println(url);&#xA;        MediaLocator ml;&#xA;&#xA;        if (url.indexOf(":") > 0 &amp;&amp; (ml = new MediaLocator(url)) != null)&#xA;            return ml;&#xA;&#xA;        if (url.startsWith(File.separator)) {&#xA;            if ((ml = new MediaLocator("file:" &#x2B; url)) != null)&#xA;                return ml;&#xA;        } else {&#xA;            String file = "file:" &#x2B; System.getProperty("user.dir") &#x2B; File.separator &#x2B; url;&#xA;            if ((ml = new MediaLocator(file)) != null)&#xA;                return ml;&#xA;        }&#xA;&#xA;        return null;&#xA;    }&#xA;&#xA;    ///////////////////////////////////////////////&#xA;    //&#xA;    // Inner classes.&#xA;    ///////////////////////////////////////////////&#xA;&#xA;    /**&#xA;     * A DataSource to read from a list of JPEG image files and turn that into a&#xA;     * stream of JMF buffers. The DataSource is not seekable or positionable.&#xA;     */&#xA;    class ImageDataSource extends PullBufferDataSource {&#xA;&#xA;        ImageSourceStream streams[];&#xA;&#xA;        ImageDataSource(int width, int height, int frameRate, Vector images) {&#xA;            streams = new ImageSourceStream[1];&#xA;            streams[0] = new ImageSourceStream(width, height, frameRate, images);&#xA;        }&#xA;&#xA;        public void setLocator(MediaLocator source) {&#xA;        }&#xA;&#xA;        public MediaLocator getLocator() {&#xA;            return null;&#xA;        }&#xA;&#xA;        /**&#xA;         * Content type is of RAW since we are sending buffers of video frames&#xA;         * without a container format.&#xA;         */&#xA;        public String getContentType() {&#xA;            return ContentDescriptor.RAW;&#xA;        }&#xA;&#xA;        public void connect() {&#xA;        }&#xA;&#xA;        public void disconnect() {&#xA;        }&#xA;&#xA;        public void start() {&#xA;        }&#xA;&#xA;        public void stop() {&#xA;        }&#xA;&#xA;        /**&#xA;         * Return the ImageSourceStreams.&#xA;         */&#xA;        public PullBufferStream[] getStreams() {&#xA;            return streams;&#xA;        }&#xA;&#xA;        /**&#xA;         * We could have derived the duration from the number of frames and&#xA;         * frame rate. But for the purpose of this program, it&#x27;s not necessary.&#xA;         */&#xA;        public Time getDuration() {&#xA;            return DURATION_UNKNOWN;&#xA;        }&#xA;&#xA;        public Object[] getControls() {&#xA;            return new Object[0];&#xA;        }&#xA;&#xA;        public Object getControl(String type) {&#xA;            return null;&#xA;        }&#xA;    }&#xA;&#xA;    /**&#xA;     * The source stream to go along with ImageDataSource.&#xA;     */&#xA;    class ImageSourceStream implements PullBufferStream {&#xA;&#xA;        Vector images;&#xA;        int width, height;&#xA;        VideoFormat format;&#xA;&#xA;        int nextImage = 0; // index of the next image to be read.&#xA;        boolean ended = false;&#xA;&#xA;        public ImageSourceStream(int width, int height, int frameRate, Vector images) {&#xA;            this.width = width;&#xA;            this.height = height;&#xA;            this.images = images;&#xA;&#xA;            format = new JPEGFormat(new Dimension(width, height), Format.NOT_SPECIFIED, Format.byteArray,&#xA;                    (float) frameRate, 75, JPEGFormat.DEC_422);&#xA;        }&#xA;&#xA;        /**&#xA;         * We should never need to block assuming data are read from files.&#xA;         */&#xA;        public boolean willReadBlock() {&#xA;            return false;&#xA;        }&#xA;&#xA;        /**&#xA;         * This is called from the Processor to read a frame worth of video&#xA;         * data.&#xA;         */&#xA;        public void read(Buffer buf) throws IOException {&#xA;&#xA;            // Check if we&#x27;ve finished all the frames.&#xA;            if (nextImage >= images.size()) {&#xA;                // We are done. Set EndOfMedia.&#xA;                System.err.println("Done reading all images.");&#xA;                buf.setEOM(true);&#xA;                buf.setOffset(0);&#xA;                buf.setLength(0);&#xA;                ended = true;&#xA;                return;&#xA;            }&#xA;&#xA;            String imageFile = (String) images.elementAt(nextImage);&#xA;            nextImage&#x2B;&#x2B;;&#xA;&#xA;            System.err.println("  - reading image file: " &#x2B; imageFile);&#xA;&#xA;            // Open a random access file for the next image.&#xA;            RandomAccessFile raFile;&#xA;            raFile = new RandomAccessFile(imageFile, "r");&#xA;&#xA;            byte data[] = null;&#xA;&#xA;            // Check the input buffer type &amp; size.&#xA;&#xA;            if (buf.getData() instanceof byte[])&#xA;                data = (byte[]) buf.getData();&#xA;&#xA;            // Check to see the given buffer is big enough for the frame.&#xA;            if (data == null || data.length &lt; raFile.length()) {&#xA;                data = new byte[(int) raFile.length()];&#xA;                buf.setData(data);&#xA;            }&#xA;&#xA;            // Read the entire JPEG image from the file.&#xA;            raFile.readFully(data, 0, (int) raFile.length());&#xA;&#xA;            System.err.println("    read " &#x2B; raFile.length() &#x2B; " bytes.");&#xA;&#xA;            buf.setOffset(0);&#xA;            buf.setLength((int) raFile.length());&#xA;            buf.setFormat(format);&#xA;            buf.setFlags(buf.getFlags() | buf.FLAG_KEY_FRAME);&#xA;&#xA;            // Close the random access file.&#xA;            raFile.close();&#xA;        }&#xA;&#xA;        /**&#xA;         * Return the format of each video frame. That will be JPEG.&#xA;         */&#xA;        public Format getFormat() {&#xA;            return format;&#xA;        }&#xA;&#xA;        public ContentDescriptor getContentDescriptor() {&#xA;            return new ContentDescriptor(ContentDescriptor.RAW);&#xA;        }&#xA;&#xA;        public long getContentLength() {&#xA;            return 0;&#xA;        }&#xA;&#xA;        public boolean endOfStream() {&#xA;            return ended;&#xA;        }&#xA;&#xA;        public Object[] getControls() {&#xA;            return new Object[0];&#xA;        }&#xA;&#xA;        public Object getControl(String type) {&#xA;            return null;&#xA;        }&#xA;    }&#xA;}&#xA;</output></height></width>

    &#xA;&#xA;

    I am getting

    &#xA;&#xA;

        Cannot create the DataSink: javax.media.NoDataSinkException: Cannot find a DataSink for: com.sun.media.multiplexer.BasicMux$BasicMuxDataSource@d7b1517&#xA;javax.media.NoDataSinkException: Cannot find a DataSink for: com.sun.media.multiplexer.BasicMux$BasicMuxDataSource@d7b1517&#xA;    at javax.media.Manager.createDataSink(Manager.java:1894)&#xA;    at com.ecomm.pl4mms.test.JpegImagesToMovie.createDataSink(JpegImagesToMovie.java:168)&#xA;    at com.ecomm.pl4mms.test.JpegImagesToMovie.doIt(JpegImagesToMovie.java:104)&#xA;    at com.ecomm.pl4mms.test.JpegImagesToMovie.main(JpegImagesToMovie.java:330)&#xA;

    &#xA;&#xA;

    Please help me to resolve this and let me what can be the cause of this

    &#xA;&#xA;

    I am using java 1.8 and trying to create video with jpeg images and using

    &#xA;&#xA;

    javax.media to perform this action. and i followed http://www.oracle.com/technetwork/java/javase/documentation/jpegimagestomovie-176885.html&#xA;to write the code

    &#xA;

  • Play video using mse (media source extension) in google chrome

    23 août 2019, par liyuqihxc

    I’m working on a project that convert rtsp stream (ffmpeg) and play it on the web page (signalr + mse).

    So far it works pretty much as I expected on the latest version of edge and firefox, but not chrome.

    here’s the code

    public class WebmMediaStreamContext
    {
       private Process _ffProcess;
       private readonly string _cmd;
       private byte[] _initSegment;
       private Task _readMediaStreamTask;
       private CancellationTokenSource _cancellationTokenSource;

       private const string _CmdTemplate = "-i {0} -c:v libvpx -tile-columns 4 -frame-parallel 1 -keyint_min 90 -g 90 -f webm -dash 1 pipe:";

       public static readonly byte[] ClusterStart = { 0x1F, 0x43, 0xB6, 0x75, 0x01, 0x00, 0x00, 0x00 };

       public event EventHandler<clusterreadyeventargs> ClusterReadyEvent;

       public WebmMediaStreamContext(string rtspFeed)
       {
           _cmd = string.Format(_CmdTemplate, rtspFeed);
       }

       public async Task StartConverting()
       {
           if (_ffProcess != null)
               throw new InvalidOperationException();

           _ffProcess = new Process();
           _ffProcess.StartInfo = new ProcessStartInfo
           {
               FileName = "ffmpeg/ffmpeg.exe",
               Arguments = _cmd,
               UseShellExecute = false,
               CreateNoWindow = true,
               RedirectStandardOutput = true
           };
           _ffProcess.Start();

           _initSegment = await ParseInitSegmentAndStartReadMediaStream();
       }

       public byte[] GetInitSegment()
       {
           return _initSegment;
       }

       // Find the first cluster, and everything before it is the InitSegment
       private async Task ParseInitSegmentAndStartReadMediaStream()
       {
           Memory<byte> buffer = new byte[10 * 1024];
           int length = 0;
           while (length != buffer.Length)
           {
               length += await _ffProcess.StandardOutput.BaseStream.ReadAsync(buffer.Slice(length));
               int cluster = buffer.Span.IndexOf(ClusterStart);
               if (cluster >= 0)
               {
                   _cancellationTokenSource = new CancellationTokenSource();
                   _readMediaStreamTask = new Task(() => ReadMediaStreamProc(buffer.Slice(cluster, length - cluster).ToArray(), _cancellationTokenSource.Token), _cancellationTokenSource.Token, TaskCreationOptions.LongRunning);
                   _readMediaStreamTask.Start();
                   return buffer.Slice(0, cluster).ToArray();
               }
           }

           throw new InvalidOperationException();
       }

       private void ReadMoreBytes(Span<byte> buffer)
       {
           int size = buffer.Length;
           while (size > 0)
           {
               int len = _ffProcess.StandardOutput.BaseStream.Read(buffer.Slice(buffer.Length - size));
               size -= len;
           }
       }

       // Parse every single cluster and fire ClusterReadyEvent
       private void ReadMediaStreamProc(byte[] bytesRead, CancellationToken cancel)
       {
           Span<byte> buffer = new byte[5 * 1024 * 1024];
           bytesRead.CopyTo(buffer);
           int bufferEmptyIndex = bytesRead.Length;

           do
           {
               if (bufferEmptyIndex &lt; ClusterStart.Length + 4)
               {
                   ReadMoreBytes(buffer.Slice(bufferEmptyIndex, 1024));
                   bufferEmptyIndex += 1024;
               }

               int clusterDataSize = BitConverter.ToInt32(
                   buffer.Slice(ClusterStart.Length, 4)
                   .ToArray()
                   .Reverse()
                   .ToArray()
               );
               int clusterSize = ClusterStart.Length + 4 + clusterDataSize;
               if (clusterSize > buffer.Length)
               {
                   byte[] newBuffer = new byte[clusterSize];
                   buffer.Slice(0, bufferEmptyIndex).CopyTo(newBuffer);
                   buffer = newBuffer;
               }

               if (bufferEmptyIndex &lt; clusterSize)
               {
                   ReadMoreBytes(buffer.Slice(bufferEmptyIndex, clusterSize - bufferEmptyIndex));
                   bufferEmptyIndex = clusterSize;
               }

               ClusterReadyEvent?.Invoke(this, new ClusterReadyEventArgs(buffer.Slice(0, bufferEmptyIndex).ToArray()));

               bufferEmptyIndex = 0;
           } while (!cancel.IsCancellationRequested);
       }
    }
    </byte></byte></byte></clusterreadyeventargs>

    I use ffmpeg to convert the rtsp stream to vp8 WEBM byte stream and parse it to "Init Segment" (ebml head、info、tracks...) and "Media Segment" (cluster), then send it to browser via signalR

    $(function () {

       var mediaSource = new MediaSource();
       var mimeCodec = 'video/webm; codecs="vp8"';

       var video = document.getElementById('video');

       mediaSource.addEventListener('sourceopen', callback, false);
       function callback(e) {
           var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
           var queue = [];

           sourceBuffer.addEventListener('updateend', function () {
               if (queue.length === 0) {
                   return;
               }

               var base64 = queue[0];
               if (base64.length === 0) {
                   mediaSource.endOfStream();
                   queue.shift();
                   return;
               } else {
                   var buffer = new Uint8Array(atob(base64).split("").map(function (c) {
                       return c.charCodeAt(0);
                   }));
                   sourceBuffer.appendBuffer(buffer);
                   queue.shift();
               }
           }, false);

           var connection = new signalR.HubConnectionBuilder()
               .withUrl("/signalr-video")
               .configureLogging(signalR.LogLevel.Information)
               .build();
           connection.start().then(function () {
               connection.stream("InitVideoReceive")
                   .subscribe({
                       next: function(item) {
                           if (queue.length === 0 &amp;&amp; !!!sourceBuffer.updating) {
                               var buffer = new Uint8Array(atob(item).split("").map(function (c) {
                                   return c.charCodeAt(0);
                               }));
                               sourceBuffer.appendBuffer(buffer);
                               console.log(blockindex++ + " : " + buffer.byteLength);
                           } else {
                               queue.push(item);
                           }
                       },
                       complete: function () {
                           queue.push('');
                       },
                       error: function (err) {
                           console.error(err);
                       }
                   });
           });
       }
       video.src = window.URL.createObjectURL(mediaSource);
    })

    chrome just play the video for 3 5 seconds and then stop for buffering, even though there are plenty of cluster transfered and inserted into SourceBuffer.

    here’s the information in chrome ://media-internals/

    Player Properties :

    render_id: 217
    player_id: 1
    origin_url: http://localhost:52531/
    frame_url: http://localhost:52531/
    frame_title: Home Page
    url: blob:http://localhost:52531/dcb25d89-9830-40a5-ba88-33c13b5c03eb
    info: Selected FFmpegVideoDecoder for video decoding, config: codec: vp8 format: 1 profile: vp8 coded size: [1280,720] visible rect: [0,0,1280,720] natural size: [1280,720] has extra data? false encryption scheme: Unencrypted rotation: 0°
    pipeline_state: kSuspended
    found_video_stream: true
    video_codec_name: vp8
    video_dds: false
    video_decoder: FFmpegVideoDecoder
    duration: unknown
    height: 720
    width: 1280
    video_buffering_state: BUFFERING_HAVE_NOTHING
    for_suspended_start: false
    pipeline_buffering_state: BUFFERING_HAVE_NOTHING
    event: PAUSE

    Log

    Timestamp       Property            Value
    00:00:00 00     origin_url          http://localhost:52531/
    00:00:00 00     frame_url           http://localhost:52531/
    00:00:00 00     frame_title         Home Page
    00:00:00 00     url                 blob:http://localhost:52531/dcb25d89-9830-40a5-ba88-33c13b5c03eb
    00:00:00 00     info                ChunkDemuxer: buffering by DTS
    00:00:00 35     pipeline_state      kStarting
    00:00:15 213    found_video_stream  true
    00:00:15 213    video_codec_name    vp8
    00:00:15 216    video_dds           false
    00:00:15 216    video_decoder       FFmpegVideoDecoder
    00:00:15 216    info                Selected FFmpegVideoDecoder for video decoding, config: codec: vp8 format: 1 profile: vp8 coded size: [1280,720] visible rect: [0,0,1280,720] natural size: [1280,720] has extra data? false encryption scheme: Unencrypted rotation: 0°
    00:00:15 216    pipeline_state      kPlaying
    00:00:15 213    duration            unknown
    00:00:16 661    height              720
    00:00:16 661    width               1280
    00:00:16 665    video_buffering_state       BUFFERING_HAVE_ENOUGH
    00:00:16 665    for_suspended_start         false
    00:00:16 665    pipeline_buffering_state    BUFFERING_HAVE_ENOUGH
    00:00:16 667    pipeline_state      kSuspending
    00:00:16 670    pipeline_state      kSuspended
    00:00:52 759    info                Effective playback rate changed from 0 to 1
    00:00:52 759    event               PLAY
    00:00:52 759    pipeline_state      kResuming
    00:00:52 760    video_dds           false
    00:00:52 760    video_decoder       FFmpegVideoDecoder
    00:00:52 760    info                Selected FFmpegVideoDecoder for video decoding, config: codec: vp8 format: 1 profile: vp8 coded size: [1280,720] visible rect: [0,0,1280,720] natural size: [1280,720] has extra data? false encryption scheme: Unencrypted rotation: 0°
    00:00:52 760    pipeline_state      kPlaying
    00:00:52 793    height              720
    00:00:52 793    width               1280
    00:00:52 798    video_buffering_state       BUFFERING_HAVE_ENOUGH
    00:00:52 798    for_suspended_start         false
    00:00:52 798    pipeline_buffering_state    BUFFERING_HAVE_ENOUGH
    00:00:56 278    video_buffering_state       BUFFERING_HAVE_NOTHING
    00:00:56 295    for_suspended_start         false
    00:00:56 295    pipeline_buffering_state    BUFFERING_HAVE_NOTHING
    00:01:20 717    event               PAUSE
    00:01:33 538    event               PLAY
    00:01:35 94     event               PAUSE
    00:01:55 561    pipeline_state      kSuspending
    00:01:55 563    pipeline_state      kSuspended

    Can someone tell me what’s wrong with my code, or dose chrome require some magic configuration to work ?

    Thanks 

    Please excuse my english :)