问题描述
我正在获取字节流[],这些字节最终是h264帧,我想使用TextureView将其流传输到android。
我知道字节的顺序和结构是可以的,因为我可以将它们保存到文件中,然后使用VLC媒体播放器将其打开并播放视频,尽管我一直在努力TextureView。
这是我的片段:
public class HelpFragment extends Fragment implements TextureView.SurfaceTextureListener {
private static final Logger Log = Logger.getLogger(HelpFragment.class.getName());
private TextureView m_surface;// View that contains the Surface Texture
private H264Provider FrameProvider;// Object that connects to our server and gets H264 frames
private MediaCodec m_codec;// Media decoder
private DecodeFramesTask m_frameTask;// AsyncTask that takes H264 frames and uses the decoder to update the Surface Texture
@Override
public View onCreateView(@NonNull LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.help_fragment,container,false);
// Get a referance to the TextureView in the UI
m_surface = (TextureView) root.findViewById(R.id.textureView);
// Add this class as a call back so we can catch the events from the Surface Texture
m_surface.setSurfaceTextureListener(this);
return root;
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface,int width,int height) {
// Create the format settinsg for the MediaCodec
MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC,1280,720);// MIMETYPE: a two-part identifier for file formats and format contents
// Set the buffer size
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE,100000);
format.setInteger(MediaFormat.KEY_FRAME_RATE,30);
try {
// Get an instance of MediaCodec and give it its Mime type
m_codec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
// Configure the Codec
m_codec.configure(format,new Surface(m_surface.getSurfaceTexture()),null,0);
// Start the codec
m_codec.start();
// Create the AsyncTask to get the frames and decode them using the Codec
m_frameTask = new DecodeFramesTask();
m_frameTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface,int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
private class DecodeFramesTask extends AsyncTask<String,String,String> {
@Override
protected String doInBackground(String... data) {
while (!isCancelled()) {
// Get the next frame
byte[] frame = Frameprovider.getVideoFrame(); // -> this gives me the video frames ***
if (frame != null) {
android.util.Log.i("tag",bytesToHex(frame));
}
// Now we need to give it to the Codec to decode into the surface
// Get the input buffer from the decoder
int inputIndex = m_codec.dequeueInputBuffer(-1);// Pass in -1 here as in this example we don't have a playback time reference
// If the buffer number is valid use the buffer with that index
if (inputIndex >= 0 && frame != null) {
ByteBuffer buffer = m_codec.getInputBuffer(inputIndex);
buffer.put(frame);
// tell the decoder to process the frame
m_codec.queueInputBuffer(inputIndex,frame.length,0);
}
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outputIndex = m_codec.dequeueOutputBuffer(info,0);
if (outputIndex >= 0) {
m_codec.releaseOutputBuffer(outputIndex,true);
}
}
return "";
}
@Override
protected void onPostExecute(String result) {
try {
m_codec.stop();
m_codec.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onStop() {
super.onStop();
m_frameTask.cancel(true);
}
}
当我运行它时,我不断收到此错误:
E/MediaCodec: getBufferAndFormat - invalid operation (the index 0 is not owned by client)
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.packagename._test,PID: 11740
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:399)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.lang.IllegalStateException
at android.media.MediaCodec.getBuffer(Native Method)
at android.media.MediaCodec.getInputBuffer(MediaCodec.java:3212)
at com.packagename._test.ui.fragments.help.HelpFragment$DecodeFramesTask.doInBackground(HelpFragment.java:130)
at com.packagename._test.ui.fragments.help.HelpFragment$DecodeFramesTask.doInBackground(HelpFragment.java:112)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
编辑: 我稍微改变了帧的顺序,现在我得到了这种类型的帧,但没有暗恋:
知道为什么吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)