7 Replies - 500 Views - Last Post: 13 October 2015 - 02:22 PM

#1 TheRookie   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 31-August 14

Can't call static method.

Posted 12 October 2015 - 02:12 PM

Hi,

I cannoot call findEncoderForMimeType() static method.I know this is a really beginers question,but I can't think of an answer.

Codecs[] encoders = CodecManager.findEncodersForMimeType(MIME_TYPE);



Is This A Good Question/Topic? 0
  • +

Replies To: Can't call static method.

#2 Atli   User is offline

  • Enhance Your Calm
  • member icon

Reputation: 4241
  • View blog
  • Posts: 7,216
  • Joined: 08-June 10

Re: Can't call static method.

Posted 12 October 2015 - 03:40 PM

Why can't you call it?
Are you getting any errors? (If so, post them here.)

Can you show us where this static function is defined?
Was This Post Helpful? 0
  • +
  • -

#3 TheRookie   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 31-August 14

Re: Can't call static method.

Posted 13 October 2015 - 01:35 PM

No,I do not get any errors.
I have uploaded the two classes on gut,take a look.
Thanks.
https://github.com/B...rammer/Question

Sorry here is the line with the problem.I didn't had this problem in eclipse,but in android studio I have it.
https://github.com/B...derDebuger#L145

import java.util.ArrayList;
import java.util.HashMap;

import android.annotation.SuppressLint;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.os.Build;
import android.util.Log;
import android.util.SparseArray;

@SuppressLint("InlinedApi")
public class CodecManager {

	public final static String TAG = "CodecManager";
	
	public static final int[] SUPPORTED_COLOR_FORMATS = {
		MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar,
		MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar
	};

		public static final String[] SOFTWARE_ENCODERS = {
		"OMX.google.h264.encoder"
	};


	static class Codecs {

		public String hardwareCodec;
		public int hardwareColorFormat;

		public String softwareCodec;
		public int softwareColorFormat;
	}


	static class Selector {

		private static HashMap<String,SparseArray<ArrayList<String>>> sHardwareCodecs = new HashMap<String, SparseArray<ArrayList<String>>>();
		private static HashMap<String,SparseArray<ArrayList<String>>> sSoftwareCodecs = new HashMap<String, SparseArray<ArrayList<String>>>();


		public static Codecs findCodecsFormMimeType(String mimeType, boolean tryColorFormatSurface) {
			findSupportedColorFormats(mimeType);
			SparseArray<ArrayList<String>> hardwareCodecs = sHardwareCodecs.get(mimeType);
			SparseArray<ArrayList<String>> softwareCodecs = sSoftwareCodecs.get(mimeType);
			Codecs list = new Codecs();


			if (Build.VERSION.SDK_INT>=18 && tryColorFormatSurface) {
				int colorFormatSurface = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
				try {

					list.hardwareCodec = hardwareCodecs.get(colorFormatSurface).get(0);
					list.hardwareColorFormat = colorFormatSurface;
				} catch (Exception e) {}
				try {

					list.softwareCodec = softwareCodecs.get(colorFormatSurface).get(0);
					list.softwareColorFormat = colorFormatSurface;
				} catch (Exception e) {}

				if (list.hardwareCodec != null) {
					Log.v(TAG,"Choosen primary codec: "+list.hardwareCodec+" with color format: "+list.hardwareColorFormat);
				} else {
					Log.e(TAG,"No supported hardware codec found !");
				}
				if (list.softwareCodec != null) {
					Log.v(TAG,"Choosen secondary codec: "+list.hardwareCodec+" with color format: "+list.hardwareColorFormat);
				} else {
					Log.e(TAG,"No supported software codec found !");
				}
				return list;
			}

			for (int i=0;i<SUPPORTED_COLOR_FORMATS.length;i++) {
				try {
					list.hardwareCodec = hardwareCodecs.get(SUPPORTED_COLOR_FORMATS[i]).get(0);
					list.hardwareColorFormat = SUPPORTED_COLOR_FORMATS[i];
					break;
				} catch (Exception e) {}
			}
			for (int i=0;i<SUPPORTED_COLOR_FORMATS.length;i++) {
				try {
					list.softwareCodec = softwareCodecs.get(SUPPORTED_COLOR_FORMATS[i]).get(0);
					list.softwareColorFormat = SUPPORTED_COLOR_FORMATS[i];
					break;
				} catch (Exception e) {}
			}

			if (list.hardwareCodec != null) {
				Log.v(TAG,"Choosen primary codec: "+list.hardwareCodec+" with color format: "+list.hardwareColorFormat);
			} else {
				Log.e(TAG,"No supported hardware codec found !");
			}
			if (list.softwareCodec != null) {
				Log.v(TAG,"Choosen secondary codec: "+list.hardwareCodec+" with color format: "+list.softwareColorFormat);
			} else {
				Log.e(TAG,"No supported software codec found !");
			}

			return list;
		}			


		@SuppressLint("NewApi")
		static private void findSupportedColorFormats(String mimeType) {
			SparseArray<ArrayList<String>> softwareCodecs = new SparseArray<ArrayList<String>>();
			SparseArray<ArrayList<String>> hardwareCodecs = new SparseArray<ArrayList<String>>();

			if (sSoftwareCodecs.containsKey(mimeType)) {
				return; 
			}

			Log.v(TAG,"Searching supported color formats for mime type \""+mimeType+"\"...");


			for(int j = MediaCodecList.getCodecCount() - 1; j >= 0; j--){
				MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(j);
				if (!codecInfo.isEncoder()) continue;

				String[] types = codecInfo.getSupportedTypes();
				for (int i = 0; i < types.length; i++) {
					if (types[i].equalsIgnoreCase(mimeType)) {
						MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);

						boolean software = false;
						for (int k=0;k<SOFTWARE_ENCODERS.length;k++) {
							if (codecInfo.getName().equalsIgnoreCase(SOFTWARE_ENCODERS[i])) {
								software = true;
							}
						}


						for (int k = 0; k < capabilities.colorFormats.length; k++) {
							int format = capabilities.colorFormats[k];
							if (software) {
								if (softwareCodecs.get(format) == null) softwareCodecs.put(format, new ArrayList<String>());
								softwareCodecs.get(format).add(codecInfo.getName());
							} else {
								if (hardwareCodecs.get(format) == null) hardwareCodecs.put(format, new ArrayList<String>());
								hardwareCodecs.get(format).add(codecInfo.getName());
							}
						}

					}
				}
			}


			StringBuilder e = new StringBuilder();
			e.append("Supported color formats on this phone: ");
			for (int i=0;i<softwareCodecs.size();i++) e.append(softwareCodecs.keyAt(i)+", ");
			for (int i=0;i<hardwareCodecs.size();i++) e.append(hardwareCodecs.keyAt(i)+(i==hardwareCodecs.size()-1?".":", "));
			Log.v(TAG, e.toString());

			sSoftwareCodecs.put(mimeType, softwareCodecs);
			sHardwareCodecs.put(mimeType, hardwareCodecs);
			return;
		}


	}

	static class Translator {

		private int mOutputColorFormat;
		private int mWidth; 
		private int mHeight;
		private int mYStride;
		private int mUVStride;
		private int mYSize;
		private int mUVSize;
		private int bufferSize;
		private int i;
		private byte[] tmp;

		public Translator(int outputColorFormat, int width, int height) {
			mOutputColorFormat = outputColorFormat;
			mWidth = width;
			mHeight = height;
			mYStride   = (int) Math.ceil(mWidth / 16.0) * 16;
			mUVStride  = (int) Math.ceil( (mYStride / 2) / 16.0) * 16;
			mYSize     = mYStride * mHeight;
			mUVSize    = mUVStride * mHeight / 2;
			bufferSize = mYSize + mUVSize * 2;
			tmp = new byte[mUVSize*2];
		}

		public int getBufferSize() {
			return bufferSize;
		}

		public int getUVStride() {
			return mUVStride;
		}

		public int getYStride() {
			return mYStride;
		}

		public byte[] translate(byte[] buffer) {

			if (mOutputColorFormat == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar) {

				int wh4 = bufferSize/6; //wh4 = width*height/4
				byte tmp;
				for (i=wh4*4; i<wh4*5; i++) {
					tmp = buffer[i];
					buffer[i] = buffer[i+wh4];
					buffer[i+wh4] = tmp;
				}
			}

			else if (mOutputColorFormat == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar) {

				System.arraycopy(buffer, mYSize, tmp, 0, mUVSize*2); // Y
				for (i = 0; i < mUVSize; i++) {
					buffer[mYSize + i*2] = tmp[i + mUVSize]; // Cb (U)
					buffer[mYSize + i*2+1] = tmp[i]; // Cr (V)
				}
			}

			return buffer;
		}


	}


}


import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.ByteBuffer;

import net.majorkernelpanic.streaming.hw.CodecManager.Codec;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Base64;
import android.util.Log;

@SuppressLint("NewApi")
public class EncoderDebugger {

	public final static String TAG = "EncoderDebugger";

	private static final String PREF_PREFIX = "libstreaming-";

	private static final boolean DEBUG = false;
	
	private static final boolean VERBOSE = false;

	private static final int VERSION = 3;

	private final static int BITRATE = 1000000;

	private final static int FRAMERATE = 20;

	private final static String MIME_TYPE = "video/avc";

	private final static int NB_DECODED = 34;
	private final static int NB_ENCODED = 50;

	private int mDecoderColorFormat, mEncoderColorFormat;
	private String mDecoderName, mEncoderName, mErrorLog;
	private MediaCodec mEncoder, mDecoder;
	private int mWidth, mHeight, mSize;
	private byte[] mSPS, mPPS;
	private byte[] mData, mInitialImage;
	private MediaFormat mDecOutputFormat;
	private NV21Convertor mNV21;
	private SharedPreferences mPreferences;
	private byte[][] mVideo, mDecodedVideo;
	private String mB64PPS, mB64SPS;

	public synchronized static void asyncDebug(final Context context, final int width, final int height) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
					debug(prefs, width, height);
				} catch (Exception e) {}
			}
		}).start();
	}
	
	public synchronized static EncoderDebugger debug(Context context, int width, int height) {
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
		return debug(prefs, width, height);
	}

	public synchronized static EncoderDebugger debug(SharedPreferences prefs, int width, int height) {
		EncoderDebugger debugger = new EncoderDebugger(prefs, width, height);
		debugger.debug();
		return debugger;
	}

	public String getB64PPS() {
		return mB64PPS;
	}

	public String getB64SPS() {
		return mB64SPS;
	}

	public String getEncoderName() {
		return mEncoderName;
	}

	public int getEncoderColorFormat() {
		return mEncoderColorFormat;
	}

	public NV21Convertor getNV21Convertor() {
		return mNV21;
	}

	public String getErrorLog() {
		return mErrorLog;
	}

	private EncoderDebugger(SharedPreferences prefs, int width, int height) {
		mPreferences = prefs;
		mWidth = width;
		mHeight = height;
		mSize = width*height;
		reset();
	}

	private void reset() {
		mNV21 = new NV21Convertor();
		mVideo = new byte[NB_ENCODED][];
		mDecodedVideo = new byte[NB_DECODED][];
		mErrorLog = "";
		mPPS = null;
		mSPS = null;		
	}

	private void debug() {
		
		if (!checkTestNeeded()) {
			String resolution = mWidth+"x"+mHeight+"-";			

			boolean success = mPreferences.getBoolean(PREF_PREFIX+resolution+"success",false);
			if (!success) {
				throw new RuntimeException("Phone not supported with this resolution ("+mWidth+"x"+mHeight+")");
			}

			mNV21.setSize(mWidth, mHeight);
			mNV21.setSliceHeigth(mPreferences.getInt(PREF_PREFIX+resolution+"sliceHeight", 0));
			mNV21.setStride(mPreferences.getInt(PREF_PREFIX+resolution+"stride", 0));
			mNV21.setYPadding(mPreferences.getInt(PREF_PREFIX+resolution+"padding", 0));
			mNV21.setPlanar(mPreferences.getBoolean(PREF_PREFIX+resolution+"planar", false));
			mNV21.setColorPanesReversed(mPreferences.getBoolean(PREF_PREFIX+resolution+"reversed", false));
			mEncoderName = mPreferences.getString(PREF_PREFIX+resolution+"encoderName", "");
			mEncoderColorFormat = mPreferences.getInt(PREF_PREFIX+resolution+"colorFormat", 0);
			mB64PPS = mPreferences.getString(PREF_PREFIX+resolution+"pps", "");
			mB64SPS = mPreferences.getString(PREF_PREFIX+resolution+"sps", "");

			return;
		}

		if (VERBOSE) Log.d(TAG, ">>>> Testing the phone for resolution "+mWidth+"x"+mHeight);
		
		Codec[] encoders = CodecManager.findEncodersForMimeType(MIME_TYPE);
		Codec[] decoders = CodecManager.findDecodersForMimeType(MIME_TYPE);

		int count = 0, n = 1;
		for (int i=0;i<encoders.length;i++) {
			count += encoders[i].formats.length;
		}
		
		for (int i=0;i<encoders.length;i++) {
			for (int j=0;j<encoders[i].formats.length;j++) {
				reset();
				
				mEncoderName = encoders[i].name;
				mEncoderColorFormat = encoders[i].formats[j];

				if (VERBOSE) Log.v(TAG, ">> Test "+(n++)+"/"+count+": "+mEncoderName+" with color format "+mEncoderColorFormat+" at "+mWidth+"x"+mHeight);
				
				mNV21.setSize(mWidth, mHeight);
				mNV21.setSliceHeigth(mHeight);
				mNV21.setStride(mWidth);
				mNV21.setYPadding(0);
				mNV21.setEncoderColorFormat(mEncoderColorFormat);

				createTestImage();
				mData = mNV21.convert(mInitialImage);

				try {

					configureEncoder();
					searchSPSandPPS();
					
					if (VERBOSE) Log.v(TAG, "SPS and PPS in b64: SPS="+mB64SPS+", PPS="+mB64PPS);

					encode();

					boolean decoded = false;
					for (int k=0;k<decoders.length && !decoded;k++) {
						for (int l=0;l<decoders[k].formats.length && !decoded;l++) {
							mDecoderName = decoders[k].name;
							mDecoderColorFormat = decoders[k].formats[l];
							try {
								configureDecoder();
							} catch (Exception e) {
								if (VERBOSE) Log.d(TAG, mDecoderName+" can't be used with "+mDecoderColorFormat+" at "+mWidth+"x"+mHeight);
								releaseDecoder();
								break;
							}
							try {
								decode(true);
								if (VERBOSE) Log.d(TAG, mDecoderName+" successfully decoded the NALs (color format "+mDecoderColorFormat+")");
								decoded = true;
							} catch (Exception e) {
								if (VERBOSE) Log.e(TAG, mDecoderName+" failed to decode the NALs");
								e.printStackTrace();
							} finally {
								releaseDecoder();
							}
						}
					}

					if (!decoded) throw new RuntimeException("Failed to decode NALs from the encoder.");

					if (!compareLumaPanes()) {
						throw new RuntimeException("It is likely that stride!=width");
					}

					int padding;
					if ((padding = checkPaddingNeeded())>0) {
						if (padding<4096) {
							if (VERBOSE) Log.d(TAG, "Some padding is needed: "+padding);
							mNV21.setYPadding(padding);
							createTestImage();
							mData = mNV21.convert(mInitialImage);
							encodeDecode();
						} else {
							throw new RuntimeException("It is likely that sliceHeight!=height");
						}
					}

					createTestImage();
					if (!compareChromaPanes(false)) {
						if (compareChromaPanes(true)) {
							mNV21.setColorPanesReversed(true);
							if (VERBOSE) Log.d(TAG, "U and V pane are reversed");
						} else {
							throw new RuntimeException("Incorrect U or V pane...");
						}
					}

					saveTestResult(true);
					Log.v(TAG, "The encoder "+mEncoderName+" is usable with resolution "+mWidth+"x"+mHeight);
					return;

				} catch (Exception e) {
					StringWriter sw = new StringWriter();
					PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw);
					String stack = sw.toString();
					String str = "Encoder "+mEncoderName+" cannot be used with color format "+mEncoderColorFormat;
					if (VERBOSE) Log.e(TAG, str, e);
					mErrorLog += str + "\n" + stack;
					e.printStackTrace();
				} finally {
					releaseEncoder();
				}

			}
		}

		saveTestResult(false);
		Log.e(TAG,"No usable encoder were found on the phone for resolution "+mWidth+"x"+mHeight);
		throw new RuntimeException("No usable encoder were found on the phone for resolution "+mWidth+"x"+mHeight);

	}

	private boolean checkTestNeeded() {
		String resolution = mWidth+"x"+mHeight+"-";

		if (DEBUG || mPreferences==null) return true;

		if (mPreferences.contains(PREF_PREFIX+resolution+"lastSdk")) {
			int lastSdk = mPreferences.getInt(PREF_PREFIX+resolution+"lastSdk", 0);
			int lastVersion = mPreferences.getInt(PREF_PREFIX+resolution+"lastVersion", 0);
			if (Build.VERSION.SDK_INT>lastSdk || VERSION>lastVersion) {
				return true;
			}
		} else {
			return true;
		}
		return false;
	}

	private void saveTestResult(boolean success) {
		String resolution = mWidth+"x"+mHeight+"-";
		Editor editor = mPreferences.edit();

		editor.putBoolean(PREF_PREFIX+resolution+"success", success);

		if (success) {
			editor.putInt(PREF_PREFIX+resolution+"lastSdk", Build.VERSION.SDK_INT);
			editor.putInt(PREF_PREFIX+resolution+"lastVersion", VERSION);
			editor.putInt(PREF_PREFIX+resolution+"sliceHeight", mNV21.getSliceHeigth());
			editor.putInt(PREF_PREFIX+resolution+"stride", mNV21.getStride());
			editor.putInt(PREF_PREFIX+resolution+"padding", mNV21.getYPadding());
			editor.putBoolean(PREF_PREFIX+resolution+"planar", mNV21.getPlanar());
			editor.putBoolean(PREF_PREFIX+resolution+"reversed", mNV21.getUVPanesReversed());
			editor.putString(PREF_PREFIX+resolution+"encoderName", mEncoderName);
			editor.putInt(PREF_PREFIX+resolution+"colorFormat", mEncoderColorFormat);
			editor.putString(PREF_PREFIX+resolution+"encoderName", mEncoderName);
			editor.putString(PREF_PREFIX+resolution+"pps", mB64PPS);
			editor.putString(PREF_PREFIX+resolution+"sps", mB64SPS);
		}

		editor.commit();
	}

	private void createTestImage() {
		mInitialImage = new byte[3*mSize/2];
		for (int i=0;i<mSize;i++) {
			mInitialImage[i] = (byte) (40+i%199);
		}
		for (int i=mSize;i<3*mSize/2;i+=2) {
			mInitialImage[i] = (byte) (40+i%200);
			mInitialImage[i+1] = (byte) (40+(i+99)%200);
		}

	}

	private boolean compareLumaPanes() {
		int d, e, f = 0;
		for (int j=0;j<NB_DECODED;j++) {
			for (int i=0;i<mSize;i+=10) {
				d = (mInitialImage[i]&0xFF) - (mDecodedVideo[j][i]&0xFF);
				e = (mInitialImage[i+1]&0xFF) - (mDecodedVideo[j][i+1]&0xFF);
				d = d<0 ? -d : d;
				e = e<0 ? -e : e;
				if (d>50 && e>50) {
					mDecodedVideo[j] = null;
					f++;
					break;
				}
			}
		}
		return f<=NB_DECODED/2;
	}

	private int checkPaddingNeeded() {
		int i = 0, j = 3*mSize/2-1, max = 0;
		int[] r = new int[NB_DECODED];
		for (int k=0;k<NB_DECODED;k++) {
			if (mDecodedVideo[k] != null) {
				i = 0;
				while (i<j && (mDecodedVideo[k][j-i]&0xFF)<50) i+=2;
				if (i>0) {
					r[k] = ((i>>6)<<6);
					max = r[k]>max ? r[k] : max;
					if (VERBOSE) Log.e(TAG,"Padding needed: "+r[k]);
				} else {
					if (VERBOSE) Log.v(TAG,"No padding needed.");
				}
			}
		}

		return ((max>>6)<<6);
	}

	private boolean compareChromaPanes(boolean crossed) {
		int d, f = 0;

		for (int j=0;j<NB_DECODED;j++) {
			if (mDecodedVideo[j] != null) {
				if (!crossed) {
					for (int i=mSize;i<3*mSize/2;i+=1) {
						d = (mInitialImage[i]&0xFF) - (mDecodedVideo[j][i]&0xFF);
						d = d<0 ? -d : d;
						if (d>50) {
							f++;
							break;
						}
					}

				} else {
					for (int i=mSize;i<3*mSize/2;i+=2) {
						d = (mInitialImage[i]&0xFF) - (mDecodedVideo[j][i+1]&0xFF);
						d = d<0 ? -d : d;
						if (d>50) {
							f++;
						}
					}
				}
			}
		}
		return f<=NB_DECODED/2;
	}	

	private void convertToNV21(int k) {
		byte[] buffer = new byte[3*mSize/2];

		int stride = mWidth, sliceHeight = mHeight;
		int colorFormat = mDecoderColorFormat;
		boolean planar = false;

		if (mDecOutputFormat != null) {
			MediaFormat format = mDecOutputFormat;
			if (format != null) {
				if (format.containsKey("slice-height")) {
					sliceHeight = format.getInteger("slice-height");
					if (sliceHeight<mHeight) sliceHeight = mHeight;
				}
				if (format.containsKey("stride")) {
					stride = format.getInteger("stride");
					if (stride<mWidth) stride = mWidth;
				}
				if (format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
					if (format.getInteger(MediaFormat.KEY_COLOR_FORMAT)>0) {
						colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
					}
				}
			}
		}

		switch (colorFormat) {
		case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
		case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
		case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
			planar = false;
			break;	
		case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
		case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
			planar = true;
			break;
		}

		for (int i=0;i<mSize;i++) {
			if (i%mWidth==0) i+=stride-mWidth;
			buffer[i] = mDecodedVideo[k][i];
		}

		if (!planar) {
			for (int i=0,j=0;j<mSize/4;i+=1,j+=1) {
				if (i%mWidth/2==0) i+=(stride-mWidth)/2;
				buffer[mSize+2*j+1] = mDecodedVideo[k][stride*sliceHeight+2*i];
				buffer[mSize+2*j] = mDecodedVideo[k][stride*sliceHeight+2*i+1];
			}
		} else {
			for (int i=0,j=0;j<mSize/4;i+=1,j+=1) {
				if (i%mWidth/2==0) i+=(stride-mWidth)/2;
				buffer[mSize+2*j+1] = mDecodedVideo[k][stride*sliceHeight+i];
				buffer[mSize+2*j] = mDecodedVideo[k][stride*sliceHeight*5/4+i];
			}
		}

		mDecodedVideo[k] = buffer;

	}
	private void configureEncoder() throws IOException  {
		mEncoder = MediaCodec.createByCodecName(mEncoderName);
		MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
		mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BITRATE);
		mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAMERATE);	
		mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mEncoderColorFormat);
		mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
		mEncoder.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
		mEncoder.start();
	}

	private void releaseEncoder() {
		if (mEncoder != null) {
			try {
				mEncoder.stop();
			} catch (Exception ignore) {}
			try {
				mEncoder.release();
			} catch (Exception ignore) {}
		}
	}

	private void configureDecoder() throws IOException {
		byte[] prefix = new byte[] {0x00,0x00,0x00,0x01};

		ByteBuffer csd0 = ByteBuffer.allocate(4+mSPS.length+4+mPPS.length);
		csd0.put(new byte[] {0x00,0x00,0x00,0x01});
		csd0.put(mSPS);
		csd0.put(new byte[] {0x00,0x00,0x00,0x01});
		csd0.put(mPPS);

		mDecoder = MediaCodec.createByCodecName(mDecoderName);
		MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
		mediaFormat.setByteBuffer("csd-0", csd0);
		mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mDecoderColorFormat);
		mDecoder.configure(mediaFormat, null, null, 0);
		mDecoder.start();

		ByteBuffer[] decInputBuffers = mDecoder.getInputBuffers();

		int decInputIndex = mDecoder.dequeueInputBuffer(1000000/FRAMERATE);
		if (decInputIndex>=0) {
			decInputBuffers[decInputIndex].clear();
			decInputBuffers[decInputIndex].put(prefix);
			decInputBuffers[decInputIndex].put(mSPS);
			mDecoder.queueInputBuffer(decInputIndex, 0, decInputBuffers[decInputIndex].position(), timestamp(), 0);
		} else {
			if (VERBOSE) Log.e(TAG,"No buffer available !");
		}

		decInputIndex = mDecoder.dequeueInputBuffer(1000000/FRAMERATE);
		if (decInputIndex>=0) {
			decInputBuffers[decInputIndex].clear();
			decInputBuffers[decInputIndex].put(prefix);
			decInputBuffers[decInputIndex].put(mPPS);
			mDecoder.queueInputBuffer(decInputIndex, 0, decInputBuffers[decInputIndex].position(), timestamp(), 0);
		} else {
			if (VERBOSE) Log.e(TAG,"No buffer available !");
		}


	}

	private void releaseDecoder() {
		if (mDecoder != null) {
			try {
				mDecoder.stop();
			} catch (Exception ignore) {}
			try {
				mDecoder.release();
			} catch (Exception ignore) {}
		}
	}	

	private long searchSPSandPPS() {

		ByteBuffer[] inputBuffers = mEncoder.getInputBuffers();
		ByteBuffer[] outputBuffers = mEncoder.getOutputBuffers();
		BufferInfo info = new BufferInfo();
		byte[] csd = new byte[128];
		int len = 0, p = 4, q = 4;
		long elapsed = 0, now = timestamp();

		while (elapsed<3000000 && (mSPS==null || mPPS==null)) {

			int bufferIndex = mEncoder.dequeueInputBuffer(1000000/FRAMERATE);
			if (bufferIndex>=0) {
				check(inputBuffers[bufferIndex].capacity()>=mData.length, "The input buffer is not big enough.");
				inputBuffers[bufferIndex].clear();
				inputBuffers[bufferIndex].put(mData, 0, mData.length);
				mEncoder.queueInputBuffer(bufferIndex, 0, mData.length, timestamp(), 0);
			} else {
				if (VERBOSE) Log.e(TAG,"No buffer available !");
			}


			int index = mEncoder.dequeueOutputBuffer(info, 1000000/FRAMERATE);

			if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {

				MediaFormat format = mEncoder.getOutputFormat();
				ByteBuffer spsb = format.getByteBuffer("csd-0");
				ByteBuffer ppsb = format.getByteBuffer("csd-1");
				mSPS = new byte[spsb.capacity()-4];
				spsb.position(4);
				spsb.get(mSPS,0,mSPS.length);
				mPPS = new byte[ppsb.capacity()-4];
				ppsb.position(4);
				ppsb.get(mPPS,0,mPPS.length);
				break;

			} else if (index == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
				outputBuffers = mEncoder.getOutputBuffers();
			} else if (index>=0) {

				len = info.size;
				if (len<128) {
					outputBuffers[index].get(csd,0,len);
					if (len>0 && csd[0]==0 && csd[1]==0 && csd[2]==0 && csd[3]==1) {
						while (p<len) {
							while (!(csd[p+0]==0 && csd[p+1]==0 && csd[p+2]==0 && csd[p+3]==1) && p+3<len) p++;
							if (p+3>=len) p=len;
							if ((csd[q]&0x1F)==7) {
								mSPS = new byte[p-q];
								System.arraycopy(csd, q, mSPS, 0, p-q);
							} else {
								mPPS = new byte[p-q];
								System.arraycopy(csd, q, mPPS, 0, p-q);
							}
							p += 4;
							q = p;
						}
					}					
				}
				mEncoder.releaseOutputBuffer(index, false);
			}

			elapsed = timestamp() - now;
		}

		check(mPPS != null & mSPS != null, "Could not determine the SPS & PPS.");
		mB64PPS = Base64.encodeToString(mPPS, 0, mPPS.length, Base64.NO_WRAP);
		mB64SPS = Base64.encodeToString(mSPS, 0, mSPS.length, Base64.NO_WRAP);

		return elapsed;
	}

	private long encode() {
		int n = 0;
		long elapsed = 0, now = timestamp();
		int encOutputIndex = 0, encInputIndex = 0;
		BufferInfo info = new BufferInfo();
		ByteBuffer[] encInputBuffers = mEncoder.getInputBuffers();
		ByteBuffer[] encOutputBuffers = mEncoder.getOutputBuffers();

		while (elapsed<5000000) {
			encInputIndex = mEncoder.dequeueInputBuffer(1000000/FRAMERATE);
			if (encInputIndex>=0) {
				check(encInputBuffers[encInputIndex].capacity()>=mData.length, "The input buffer is not big enough.");
				encInputBuffers[encInputIndex].clear();
				encInputBuffers[encInputIndex].put(mData, 0, mData.length);
				mEncoder.queueInputBuffer(encInputIndex, 0, mData.length, timestamp(), 0);
			} else {
				if (VERBOSE) Log.d(TAG,"No buffer available !");
			}

			encOutputIndex = mEncoder.dequeueOutputBuffer(info, 1000000/FRAMERATE);
			if (encOutputIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
				encOutputBuffers = mEncoder.getOutputBuffers();
			} else if (encOutputIndex>=0) {
				mVideo[n] = new byte[info.size];
				encOutputBuffers[encOutputIndex].clear();
				encOutputBuffers[encOutputIndex].get(mVideo[n++], 0, info.size);
				mEncoder.releaseOutputBuffer(encOutputIndex, false);
				if (n>=NB_ENCODED) {
					flushMediaCodec(mEncoder);
					return elapsed;
				}
			}

			elapsed = timestamp() - now;
		}

		throw new RuntimeException("The encoder is too slow.");

	}

	private long decode(boolean withPrefix) {
		int n = 0, i = 0, j = 0;
		long elapsed = 0, now = timestamp();
		int decInputIndex = 0, decOutputIndex = 0;
		ByteBuffer[] decInputBuffers = mDecoder.getInputBuffers();
		ByteBuffer[] decOutputBuffers = mDecoder.getOutputBuffers();
		BufferInfo info = new BufferInfo();

		while (elapsed<3000000) {

			if (i<NB_ENCODED) {
				decInputIndex = mDecoder.dequeueInputBuffer(1000000/FRAMERATE);
				if (decInputIndex>=0) {
					int l1 = decInputBuffers[decInputIndex].capacity();
					int l2 = mVideo[i].length;
					decInputBuffers[decInputIndex].clear();
					
					if ((withPrefix && hasPrefix(mVideo[i])) || (!withPrefix && !hasPrefix(mVideo[i]))) {
						check(l1>=l2, "The decoder input buffer is not big enough (nal="+l2+", capacity="+l1+").");
						decInputBuffers[decInputIndex].put(mVideo[i],0,mVideo[i].length);
					} else if (withPrefix && !hasPrefix(mVideo[i])) {
						check(l1>=l2+4, "The decoder input buffer is not big enough (nal="+(l2+4)+", capacity="+l1+").");
						decInputBuffers[decInputIndex].put(new byte[] {0,0,0,1});
						decInputBuffers[decInputIndex].put(mVideo[i],0,mVideo[i].length);
					} else if (!withPrefix && hasPrefix(mVideo[i])) {
						check(l1>=l2-4, "The decoder input buffer is not big enough (nal="+(l2-4)+", capacity="+l1+").");
						decInputBuffers[decInputIndex].put(mVideo[i],4,mVideo[i].length-4);
					}
					
					mDecoder.queueInputBuffer(decInputIndex, 0, l2, timestamp(), 0);
					i++;
				} else {
					if (VERBOSE) Log.d(TAG,"No buffer available !");
				}
			}

			decOutputIndex = mDecoder.dequeueOutputBuffer(info, 1000000/FRAMERATE);
			if (decOutputIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
				decOutputBuffers = mDecoder.getOutputBuffers();
			} else if (decOutputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
				mDecOutputFormat = mDecoder.getOutputFormat();
			} else if (decOutputIndex>=0) {
				if (n>2) {
					int length = info.size;
					mDecodedVideo[j] = new byte[length];
					decOutputBuffers[decOutputIndex].clear();
					decOutputBuffers[decOutputIndex].get(mDecodedVideo[j], 0, length);
					convertToNV21(j);
					if (j>=NB_DECODED-1) {
						flushMediaCodec(mDecoder);
						if (VERBOSE) Log.v(TAG, "Decoding "+n+" frames took "+elapsed/1000+" ms");
						return elapsed;
					}
					j++;
				}
				mDecoder.releaseOutputBuffer(decOutputIndex, false);
				n++;
			}	
			elapsed = timestamp() - now;
		}

		throw new RuntimeException("The decoder did not decode anything.");

	}

	private boolean hasPrefix(byte[] nal) {
		if (nal[0] == 0 && nal[1] == 0 && nal[2] == 0 && nal[3] == 0x01)
			return true;
		else
			return false;
	}
	
	private void encodeDecode() throws IOException {
		encode();
		try {
			configureDecoder();
			decode(true);
		} finally {
			releaseDecoder();
		}
	}

	private void flushMediaCodec(MediaCodec mc) {
		int index = 0;
		BufferInfo info = new BufferInfo();
		while (index != MediaCodec.INFO_TRY_AGAIN_LATER) {
			index = mc.dequeueOutputBuffer(info, 1000000/FRAMERATE);
			if (index>=0) {
				mc.releaseOutputBuffer(index, false);
			}
		}
	}

	private void check(boolean cond, String message) {
		if (!cond) {
			if (VERBOSE) Log.e(TAG,message);
			throw new IllegalStateException(message);
		}
	}

	private long timestamp() {
		return System.nanoTime()/1000;
	}

}


This post has been edited by Atli: 13 October 2015 - 01:43 PM
Reason for edit:: Added the code to the post. Makes things easier, to have the code with the question.

Was This Post Helpful? 0
  • +
  • -

#4 Atli   User is offline

  • Enhance Your Calm
  • member icon

Reputation: 4241
  • View blog
  • Posts: 7,216
  • Joined: 08-June 10

Re: Can't call static method.

Posted 13 October 2015 - 01:49 PM

Your CodecManager class doesn't seem to have either a "findEncodersForMimeType" nor a "findDecodersForMimeType" method. Where are these supposed to be defined?

If you aren't getting any errors, can you clarify how the problem presents itself?
What's happening, and how should it be happening?
Was This Post Helpful? 0
  • +
  • -

#5 TheRookie   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 31-August 14

Re: Can't call static method.

Posted 13 October 2015 - 01:56 PM

View PostAtli, on 13 October 2015 - 01:49 PM, said:

Your CodecManager class doesn't seem to have either a "findEncodersForMimeType" nor a "findDecodersForMimeType" method. Where are these supposed to be defined?

If you aren't getting any errors, can you clarify how the problem presents itself?
What's happening, and how should it be happening?



My bad. I want to acces findEncodersForMimeType,which is defined at line 42 in the CodecManager class.
Which is a constructor.Sorry I am really tired.I've been programming for multiple hours straight.

This post has been edited by TheRookie: 13 October 2015 - 01:59 PM

Was This Post Helpful? 0
  • +
  • -

#6 TheRookie   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 31-August 14

Re: Can't call static method.

Posted 13 October 2015 - 02:21 PM

Shit,you're right.That method is not defined.
I defined one similar,but not that one.Sorry again,it is a method not a constructor.
I'm going to sleep.
Was This Post Helpful? 0
  • +
  • -

#7 Atli   User is offline

  • Enhance Your Calm
  • member icon

Reputation: 4241
  • View blog
  • Posts: 7,216
  • Joined: 08-June 10

Re: Can't call static method.

Posted 13 October 2015 - 02:21 PM

You mean the findCodecsFormMimeType method of the nested Selector class?

You'd have to actually use the nested class, rather than calling the method on the parent class.
CodecManager.Selector.findCodecsFormMimeType()


Read up on nested classes to understand what's going on there.
Was This Post Helpful? 0
  • +
  • -

#8 TheRookie   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 45
  • Joined: 31-August 14

Re: Can't call static method.

Posted 13 October 2015 - 02:22 PM

View PostAtli, on 13 October 2015 - 02:21 PM, said:

You mean the findCodecsFormMimeType method of the nested Selector class?

You'd have to actually use the nested class, rather than calling the method on the parent class.
CodecManager.Selector.findCodecsFormMimeType()


Read up on nested classes to understand what's going on there.


I was misslead by the name.Lesson learned. I cannot belive how much of a retard I am :)))

This post has been edited by TheRookie: 13 October 2015 - 02:26 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1