ffmpegxugglerxuggle

IContainer.open() fails when using with custom ByteChannel to read from


I am trying to open an IContainer object which is reading from a custom input buffer rather than reading from a media file. The implementation for this custom input buffer is as below.

The code to create and open the container is as below.

// Open up the container for READING
mInputCStore = new CStore();

IContainerFormat format = IContainerFormat.make();
if (format.setInputFormat("flv") < 0) {
    throw new IllegalArgumentException("Failed to initialize the input format");
}

// Open up the container
mInputContainer = IContainer.make();
int retval = mInputContainer.open(mPlaybackContainerStore, IContainer.Type.READ, format);       
if (retval < 0) {
    // This little trick converts the non friendly integer return value into  
    // a slightly more friendly object to get a human-readable error name
    IError error = IError.make(retval);
    throw new IllegalArgumentException("could not open input container: " + mPlaybackContainerStore + "; Error: " + error.getDescription());
}

The above code throwing an exception saying that --

Exception in thread "main" java.lang.IllegalArgumentException: could not open input container: com.client.video.ContainerStore@61981853; Error: Operation not permitted

The same custom buffer when used while writing to the container is working successfully. Can someone pls help me understand what is missing in the custom buffer implementation, as far as using it in READ mode and why the reason it is failing?

package test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.util.concurrent.ConcurrentLinkedQueue;

public class CStore implements ByteChannel {
    private ConcurrentLinkedQueue<DataChunk> mChunkQueue = null;
    private int mQueueSize = 0;

    // constructor
    public CStore(String type) {
        mQueueSize = 0;
        mChunkQueue = new ConcurrentLinkedQueue<DataChunk>();
        mChunkQueue.clear();
    }

    @Override
    public void close() throws IOException {
        return;
    }

    @Override
    public boolean isOpen() {
        return false;
    }

    @Override
    public int write(ByteBuffer buffer) throws IOException {
        DataChunk chunk = new DataChunk(buffer);
        mChunkQueue.add(chunk);
        mQueueSize += chunk.getLength();
        return 0;
    }

    public int read(ByteBuffer buffer) throws IOException {

        int result = 0;

        DataChunk chunk = mChunkQueue.poll();
        if (chunk != null) {
            buffer = chunk.getBuffer();
            if (buffer != null) {
                result = 0;
            } else {
                result = 1;
            }
        }

        return result;
    }
}

Solution

  • I resolved this problem by reimplementing the read() method as below.

    public int read(ByteBuffer buffer) {
        int bytesRead = 0;
    
        if (buffer == null)
            return 0;
    
        while (buffer.hasRemaining()) {
            byte b = mBuff.get();
            buffer.put(b);
            bytesRead++;
        }
    
        return bytesRead;
    }
    

    Note that before I call this function, I am converting the mChunkQueue into a ByteBuffer mBuff. There is still scope for cleaning up this class/implementation though. But its resolved for now.