private void debug() {
		
		// If testing the phone again is not needed, 
		// we just restore the result from the shared preferences
		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);
		
		// Builds a list of available encoders and decoders we may be able to use
		// because they support some nice color formats
		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;
		}
		
		// Tries available encoders
		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);
				
				// Converts from NV21 to YUV420 with the specified parameters
				mNV21.setSize(mWidth, mHeight);
				mNV21.setSliceHeigth(mHeight);
				mNV21.setStride(mWidth);
				mNV21.setYPadding(0);
				mNV21.setEncoderColorFormat(mEncoderColorFormat);

				// /!\ NV21Convertor can directly modify the input
				createTestImage();
				mData = mNV21.convert(mInitialImage);

				try {

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

					// Feeds the encoder with an image repeatedly to produce some NAL units
					encode();

					// We now try to decode the NALs with decoders available on the phone
					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.");

					// Compares the image before and after
					if (!compareLumaPanes()) {
						// TODO: try again with a different stride
						// TODO: try again with the "stride" param
						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 {
							// TODO: try again with a different sliceHeight
							// TODO: try again with the "slice-height" param
							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);

	}
A log of all the errors that occurred during the test.
src/net/majorkernelpanic/streaming/hw/EncoderDebugger.java