media extractor show “failed to instantiate extractor”

匿名 (未验证) 提交于 2019-12-03 08:54:24

问题:

I am trying to work on media extractor for audio streaming of OGG file format on android. I have written some code with help of google documents. but it doesn't work at all. May be i have Written a wrong code or syntax As i am student. it show me failed to instantiate extractor

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);  MediaExtractor extractor = new MediaExtractor(); extractor.setDataSource("http://examplelink.com/ogg");// I cant put real link so sorry for that int numTracks = extractor.getTrackCount(); for (int i = 0; i < numTracks; ++i) {     MediaFormat format = extractor.getTrackFormat(i);     String mime = format.getString(MediaFormat.KEY_MIME);     extractor.selectTrack(i);      ByteBuffer inputBuffer = ByteBuffer.allocate(1024);     while (extractor.readSampleData(inputBuffer,0) >= 0) {             int trackIndex = (int) extractor.getSampleTime();             long presentationTimeUs = extractor.getSampleTime();     }      MediaCodec codec = MediaCodec.createDecoderByType(mime);     codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);     codec.start();     ByteBuffer[] inputBuffers = codec.getInputBuffers();     ByteBuffer[] outputBuffers = codec.getOutputBuffers();     format = codec.getOutputFormat();     Long timeoutUs=(long) 1;     for (;;) {         int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs);         if (inputBufferIndex >= 0) {             // fill inputBuffers[inputBufferIndex] with valid data             codec.queueInputBuffer(inputBufferIndex, 0, 128, 0,0);         }         MediaCodec.BufferInfo info = new BufferInfo();         int outputBufferIndex = codec.dequeueOutputBuffer(info, timeoutUs);         if (outputBufferIndex >= 0) {             // outputBuffer is ready to be processed or rendered.             codec.releaseOutputBuffer(outputBufferIndex, false);         } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {             outputBuffers = codec.getOutputBuffers();         } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {             // Subsequent data will conform to new format.             format = codec.getOutputFormat();             AudioTrack mAudioTrack = null;             mAudioTrack.setPlaybackRate(format.getInteger(MediaFormat.KEY_SAMPLE_RATE));         }         codec.stop();         codec.release();         codec = null;     } } 

}

回答1:

I ASSUME your question is "why doesn't it work at all?" Usually, this is much too big a question, but in this case it looks to me like you have not understood at all how the MediaExtractor & MediaCodec work.

Not all your fault though. The documentation is cryptic, to put it kindly. However I have succeeded in playing audio files this way.

My scheme assumes that MediaCodec implements an asynchronous queue of buffers. There seem to be about 4 buffers in this queue.

So I use 2 threads: One thread puts data from the MediaExtractor into the queue, and another thread takes decoded audio out from the queue and writes it to an AudioTrack.

I Then need to be very careful to avoid deadlock during a seek, for example. And I end up with a lot more code than yours. I don't know how to avoid that !

I am thinking of trying video. Any helpful references would be appreciated !

Don



回答2:

Code will be something below, which is working perfectly for me for local audio file in JB platform.

try{   Extractor lExt = new MediaExtractor();   lExt.setDataSource(file path); //I have tried with local file   lExt.setTrack(0); //For local file only one track will be present   MediaFormat format = lExt.getTrackFormat(0); //0 is the track ID   String mime = format.getString(MediaFormat.KEY_MIME);   MediaCodec codec = MediaCodec.createDecoderByType(mime);   codec.configure(        format,//format of input data ::decoder OR desired format of the output data:encoder        null,//Specify a surface on which to render the output of this decoder        null,//Specify a crypto object to facilitate secure decryption        0 //For Decoding, encoding use: CONFIGURE_FLAG_ENCODE         );   codec.start();   codec.flush();    //Get Input and Output buffers from codec   inputBuffers = codec.getInputBuffers();   outputBuffers = codec.getOutputBuffers();     While(condition)   {       //Get Audio data from extractor       int inputBufIndex = codec.dequeueInputBuffer(50);//Timeout set of 50 microsec       if (inputBufIndex >= 0)        {            ByteBuffer dstBuf = inputBuffers[inputBufIndex];             int sampleSize = extractor.readSampleData(dstBuf, 0);            long presentationTimeUs = extractor.getSampleTime();             codec.queueInputBuffer(inputBufIndex,                            0, //offset                            sampleSize,                            presentationTimeUs,                            0); //Use appropriate flag value            extractor.advance();         }        //Use codec to decode the data -- handle end of stream properly         MediaCodec.BufferInfo info = new  MediaCodec.BufferInfo();         info.set(0,0,0,0);         final int res = codec.dequeueOutputBuffer(info, 20000);         if (res >= 0)          {             int outputBufIndex = res;             ByteBuffer buf = outputBuffers[outputBufIndex];              byte[] chunk = new byte[info.size];             buf.get(chunk); // Read the buffer all at once             buf.clear(); // ** MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN              if (chunk.length > 0)                 //Use this chunk as it contains decoded audio dat                         codec.releaseOutputBuffer(outputBufIndex, false /* render */);          }          else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)              outputBuffers = codec.getOutputBuffers();   }   codec.stop();   codec.release();   lExt.release(); } catch(Exception ex)... 


回答3:

Setting the data source to a remote URL will require the android.permission.INTERNET permission to be declared in the AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" /> 


回答4:

Try passing it a file descriptor of an opened file, instead of a file path. It worked for me when I had this problem. I have no idea why.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!