Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Nv21字节数据在android中保存为彩色H264格式_Android_Encoding_H.264_Android Mediacodec - Fatal编程技术网

Nv21字节数据在android中保存为彩色H264格式

Nv21字节数据在android中保存为彩色H264格式,android,encoding,h.264,android-mediacodec,Android,Encoding,H.264,Android Mediacodec,我从NV21字节数据中获取视频以使用下面的代码,并保存了它。H264格式扩展名,但我的视频背景没有颜色,我想制作彩色的,我保存的是H264格式的NV21字节数据,这可能是原因吗,我如何解决这个问题 private void initCodec() { try { mMediaCodec = MediaCodec.createEncoderByType("video/avc"); } catch (IOException e) {

我从NV21字节数据中获取视频以使用下面的代码,并保存了它。H264格式扩展名,但我的视频背景没有颜色,我想制作彩色的,我保存的是H264格式的NV21字节数据,这可能是原因吗,我如何解决这个问题

    private void initCodec() {
        try {
            mMediaCodec = MediaCodec.createEncoderByType("video/avc");
        } catch (IOException e) {
            e.printStackTrace();
        }
        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",
                1280,
                720);
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 360); //video second
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
/*        mDestData = new byte[1280 * 720
                * ImageFormat.getBitsPerPixel(ImageFormat.YV12) / 8];*/

        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
        mMediaCodec.configure(mediaFormat,
                null,
                null,
                MediaCodec.CONFIGURE_FLAG_ENCODE);
        mMediaCodec.start();
}
编码NV21字节数据

    //Video format H264
private synchronized void encode(byte[] data) {

    ByteBuffer[]  inputBuffers = mMediaCodec.getInputBuffers();
    ByteBuffer[]  outputBuffers = mMediaCodec.getOutputBuffers();

    int inputBufferIndex = mMediaCodec.dequeueInputBuffer(-1);
    if (inputBufferIndex >= 0) {
        ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
        inputBuffer.capacity();
        inputBuffer.clear();
        inputBuffer.put(data);
        mMediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, 0, 0);
    } else {
        return;
    }

    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
    int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 0);
    Log.i(TAG, "outputBufferIndex-->" + outputBufferIndex);
    do {
        if (outputBufferIndex >= 0) {
            ByteBuffer outBuffer = outputBuffers[outputBufferIndex];
            System.out.println("buffer info-->" + bufferInfo.offset + "--"
                    + bufferInfo.size + "--" + bufferInfo.flags + "--"
                    + bufferInfo.presentationTimeUs);
            byte[] outData = new byte[bufferInfo.size];
            outBuffer.get(outData);
            try {
                if (bufferInfo.offset != 0) {
                    fos.write(outData, bufferInfo.offset, outData.length
                            - bufferInfo.offset);
                } else {
                    fos.write(outData, 0, outData.length);
                }
                fos.flush();
                Log.i(TAG, "out data -- > " + outData.length);
                mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
                outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo,
                        0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
            outputBuffers = mMediaCodec.getOutputBuffers();
        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
            MediaFormat format = mMediaCodec.getOutputFormat();
        }
    } while (outputBufferIndex >= 0);
}
我正在使用这种转换格式,它比旧的格式更好,但它不能提供真实的相机视图

public static byte[] YV12toYUV420Planar(byte[] input, byte[] output, int width, int height) {

    final int frameSize = (width * height);
    final int qFrameSize = frameSize/4;

    System.arraycopy(input, 0, output, 0, frameSize); // Y
    System.arraycopy(input, frameSize, output, frameSize + qFrameSize, qFrameSize); // Cr (V)
    System.arraycopy(input, frameSize + qFrameSize, output, frameSize, qFrameSize); // Cb (U)

    return output;
}
最后我打电话来了

   private CameraProxy.CameraDataCallBack callBack = new CameraProxy.CameraDataCallBack() {

        @Override
        public void onDataBack(byte[] data, long length) {
            // TODO Auto-generated method stub
            Log.i(TAG, "length . " + length);

            photo = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/", "photo"+i+".jpg");
            byte[]outpt = new byte[data.length];

            byte[] datam = YV12toYUV420Planar(data,outpt,1280,720);

            encode(datam);
}

这个功能解决了我的问题

public static byte[] NV21toYUV420Planar(byte[] input, byte[] output, int width, int height) {
    final int frameSize = width * height;
    final int qFrameSize = frameSize/4;

    System.arraycopy(input, 0, output, 0, frameSize); // Y

    byte v, u;

    for (int i = 0; i < qFrameSize; i++) {
        v = input[frameSize + i*2];
        u = input[frameSize + i*2 + 1];

        output[frameSize + i + qFrameSize] = v;
        output[frameSize + i] = u;
    }

    return output;
}
公共静态字节[]NV21TOYUV420平面(字节[]输入,字节[]输出,整数宽度,整数高度){
最终整数帧大小=宽度*高度;
最终int qFrameSize=frameSize/4;
System.arraycopy(输入,0,输出,0,帧大小);//Y
字节v,u;
对于(int i=0;i
试试这个颜色format color\u format 32BitArgB8888我只有粉红色,我的设备是棒棒糖Api 21,color\u format 32BitArgB8888是Api 23这可能是你在输入格式中指定YUV420P作为颜色格式的原因,而NV21的等价物是YUV420SP(半平面)。不需要此方法,只需将颜色格式指定为color_FormatYUV420SemiPlanar即可。