android - Incorrect decoding of H264 video stream on Nexus devices -


i'm trying use android mediacodec class decode h264 video stream of remote camera. code is:

public class remotecamera {  public interface oncameralistener {     void onconnected();     void onfailureconnection();     void ondisconnected();     void onready(); }  private static final int max_nal_len = 1024 * 1024; private static final string tag = "remotecamera";  private outputthread moutputthread;  private websocketmanager mwebsocketmanager; private oncameralistener moncameralistener;  private int msearchstate = 0; private byte[] mnaldata; private int mnaldatapos;  private mediacodec mdecoder; private mediaformat mformat; private surfaceview msurfaceview; private mediacodec.bufferinfo minfo = new mediacodec.bufferinfo(); private boolean miswaitingforsps = true;  public remotecamera(final surfaceview surfaceview, final string wss) {     msurfaceview = surfaceview;     mwebsocketmanager = new websocketmanager(wss);     mwebsocketmanager.setwslistener(new websocketmanager.onwslistener() {         @override         public void onopen() {             if (moncameralistener != null) {                 moncameralistener.onconnected();             }         }          @override         public void onclosed() {             if (moncameralistener != null) {                 moncameralistener.ondisconnected();             }         }          @override         public void onfailure() {             if (moncameralistener != null) {                 moncameralistener.onfailureconnection();             }         }          @override         public synchronized void onmessage(final bytestring bytes) {             final bytebuffer bb = bytebuffer.wrap(bytes.tobytearray());              if (miswaitingforsps) {                 if (isspsunit(bb)) {                     miswaitingforsps = false;                     if (moncameralistener != null) {                         moncameralistener.onready();                     }                 } else {                     return;                 }             }              parsedatagram(bb.array(), bytes.size());         }     });      mnaldata = new byte[max_nal_len];     mnaldatapos = 0;     try {         mdecoder = mediacodec.createdecoderbytype("video/avc");     } catch (exception e) {         log.d(tag, e.tostring());         return;     }      mformat = mediaformat.createvideoformat("video/avc", 320, 240); }  public void setoncameralistener(final oncameralistener cameralistener) {     moncameralistener = cameralistener; }  public void startstreaming() {     msurfaceview.getholder().addcallback(new surfaceholder.callback() {         @override         public void surfacecreated(surfaceholder surfaceholder) {             try {                 mdecoder.configure(mformat, msurfaceview.getholder().getsurface(), null, 0);             } catch (exception e) {                 log.d(tag, e.tostring());                 return;             }             mwebsocketmanager.wsregister();             mdecoder.start();             moutputthread = new outputthread();             moutputthread.start();         }          @override         public void surfacechanged(surfaceholder surfaceholder, int i, int i1, int i2) {          }          @override         public void surfacedestroyed(surfaceholder surfaceholder) {          }     }); }   private void feeddecoder(byte[] n, int len) {     (; ; ) {         try {             int inputbufferindex = mdecoder.dequeueinputbuffer(0);             if (inputbufferindex >= 0) {                 final bytebuffer inputbuffer = mdecoder.getinputbuffer(inputbufferindex);                 inputbuffer.put(n, 0, len);                 mdecoder.queueinputbuffer(inputbufferindex, 0, len, system.currenttimemillis(), 0);                 break;             }         } catch (exception e) {             log.d(tag, e.tostring());         }     } }  private void parsedatagram(byte[] p, int plen) {     try {         (int = 0; < plen; ++i) {             mnaldata[mnaldatapos++] = p[i];             if (mnaldatapos == max_nal_len - 1) {                 mnaldatapos = 0;             }             switch (msearchstate) {                 case 0:                 case 1:                 case 2:                     if (p[i] == 0)                         msearchstate++;                     else                         msearchstate = 0;                     break;                 case 3:                     if (p[i] == 1) {                         mnaldata[0] = 0;                         mnaldata[1] = 0;                         mnaldata[2] = 0;                         mnaldata[3] = 1;                         feeddecoder(mnaldata, mnaldatapos - 4);                         mnaldatapos = 4;                     }                     msearchstate = 0;                     break;                 default:                     break;             }         }     } catch (exception e) {         log.d(tag, e.tostring());     } }  private boolean isspsunit(final bytebuffer unit) {     return unit.get(4) == 0x67; }   private class outputthread extends thread {      @override     public void run() {         while (true) {             try {                 int outputbufferindex = mdecoder.dequeueoutputbuffer(minfo, 10);                 if (outputbufferindex >= 0) {                     mdecoder.releaseoutputbuffer(outputbufferindex, true);                 }             } catch (exception e) {                 log.d(tag, e.tostring());             }         }     } } 

i tested code on sony xperia z5 compact , yota phone 2, , works fine on these devices. picture got sony really good. tried video streamer on nexus 9 , nexus 7 devices, looks row moving top bottom. there no correct output on nexus devices: nexus results.

i know depends on native android media codec, should resolve problem , able show video on devices?

do not pass 0x00 0x00 0x00 0x01 nalu start code decoder.


Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -