Codificar video usando ffmpeg de javacv en Android provoca un bloqueo del código nativo

NOTA: He actualizado esto desde que originalmente hice la pregunta para reflejar algo de lo que aprendí sobre la carga de imágenes de cámaras en vivo en las bibliotecas de ffmpeg.

Estoy usandoffmpeg desdejavacv compilado para Android para codificar / decodificar video para mi aplicación. (Tenga en cuenta que originalmente, estaba tratando de usarffmpeg-java, pero tiene algunas bibliotecas incompatibles)

Problema original: El problema con el que me he encontrado es que actualmente obtengo cada fotograma comoBitmap (solo una simpleandroid.graphics.Bitmap) y no puedo entender cómo meter eso en el codificador.

Solución enjavacv 'sffmpeg: Use avpicture_fill (), el formato de Android supuestamente es YUV420P, aunque no puedo verificar esto hasta que se solucionen los problemas de mi codificador (a continuación).

avcodec.avpicture_fill((AVPicture)mFrame, picPointer, avutil.PIX_FMT_YUV420P, VIDEO_WIDTH, VIDEO_HEIGHT)

Problema ahora: La línea que se supone que realmente codifica los datos bloquea el hilo. Obtengo un gran seguimiento de la pila de código nativo que no puedo entender. ¿Alguien tiene una sugerencia?

Aquí está el código que estoy usando para crear instancias de todas lasffmpeg bibliotecas:

    avcodec.avcodec_register_all();
    avcodec.avcodec_init();
    avformat.av_register_all();

    mCodec = avcodec.avcodec_find_encoder(avcodec.CODEC_ID_H263);
    if (mCodec == null)
    {
        Logging.Log("Unable to find encoder.");
        return;
    }
    Logging.Log("Found encoder.");

    mCodecCtx = avcodec.avcodec_alloc_context();
    mCodecCtx.bit_rate(300000);
    mCodecCtx.codec(mCodec);
    mCodecCtx.width(VIDEO_WIDTH);
    mCodecCtx.height(VIDEO_HEIGHT);
    mCodecCtx.pix_fmt(avutil.PIX_FMT_YUV420P);
    mCodecCtx.codec_id(avcodec.CODEC_ID_H263);
    mCodecCtx.codec_type(avutil.AVMEDIA_TYPE_VIDEO);
    AVRational ratio = new AVRational();
    ratio.num(1);
    ratio.den(30);
    mCodecCtx.time_base(ratio);
    mCodecCtx.coder_type(1);
    mCodecCtx.flags(mCodecCtx.flags() | avcodec.CODEC_FLAG_LOOP_FILTER);
    mCodecCtx.me_cmp(avcodec.FF_LOSS_CHROMA);
    mCodecCtx.me_method(avcodec.ME_HEX);
    mCodecCtx.me_subpel_quality(6);
    mCodecCtx.me_range(16);
    mCodecCtx.gop_size(30);
    mCodecCtx.keyint_min(10);
    mCodecCtx.scenechange_threshold(40);
    mCodecCtx.i_quant_factor((float) 0.71);
    mCodecCtx.b_frame_strategy(1);
    mCodecCtx.qcompress((float) 0.6);
    mCodecCtx.qmin(10);
    mCodecCtx.qmax(51);
    mCodecCtx.max_qdiff(4);
    mCodecCtx.max_b_frames(1);
    mCodecCtx.refs(2);
    mCodecCtx.directpred(3);
    mCodecCtx.trellis(1);
    mCodecCtx.flags2(mCodecCtx.flags2() | avcodec.CODEC_FLAG2_BPYRAMID | avcodec.CODEC_FLAG2_WPRED | avcodec.CODEC_FLAG2_8X8DCT | avcodec.CODEC_FLAG2_FASTPSKIP);

    if (avcodec.avcodec_open(mCodecCtx, mCodec) == 0)
    {
        Logging.Log("Unable to open encoder.");
        return;
    }
    Logging.Log("Encoder opened.");

    mFrameSize = avcodec.avpicture_get_size(avutil.PIX_FMT_YUV420P, VIDEO_WIDTH, VIDEO_HEIGHT);
    Logging.Log("Frame size - '" + mFrameSize + "'.");
    //mPic = new AVPicture(mPicSize);
    mFrame = avcodec.avcodec_alloc_frame();
    if (mFrame == null)
    {
        Logging.Log("Unable to alloc frame.");
    }

Esto es lo que quiero poder ejecutar a continuación:

    BytePointer picPointer = new BytePointer(data);
    int bBuffSize = mFrameSize;

    BytePointer bBuffer = new BytePointer(bBuffSize);

    int picSize = 0;
    if ((picSize = avcodec.avpicture_fill((AVPicture)mFrame, picPointer, avutil.PIX_FMT_YUV420P, VIDEO_WIDTH, VIDEO_HEIGHT)) <= 0)
    {
        Logging.Log("Couldn't convert preview to AVPicture (" + picSize + ")");
        return;
    }
    Logging.Log("Converted preview to AVPicture (" + picSize + ")");

    VCAP_Package vPackage = new VCAP_Package();

    if (mCodecCtx.isNull())
    {
        Logging.Log("Codec Context is null!");
    }

    //encode the image
    int size = avcodec.avcodec_encode_video(mCodecCtx, bBuffer, bBuffSize, mFrame);

    int totalSize = 0;
    while (size >= 0)
    {
        totalSize += size;
        Logging.Log("Encoded '" + size + "' bytes.");
        //Get any delayed frames
        size = avcodec.avcodec_encode_video(mCodecCtx, bBuffer, bBuffSize, null); 
    }
    Logging.Log("Finished encoding. (" + totalSize + ")");

Pero, a partir de ahora, no sé cómo colocar el mapa de bits en la pieza correcta o si tengo esa configuración correcta.

Algunas notas sobre el código: -VIDEO_WIDTH = 352 -VIDEO_HEIGHT = 288 -VIDEO_FPS = 30;

Respuestas a la pregunta(4)

Su respuesta a la pregunta