Кодирование видео с использованием ffmpeg из javacv на Android вызывает сбой собственного кода

ПРИМЕЧАНИЕ: я обновлял это с тех пор, как первоначально задавал вопрос, чтобы отразить кое-что из того, что я узнал о загрузке изображений с живых камер в библиотеки ffmpeg.

Я используюffmpeg изjavacv скомпилирован для Android для кодирования / декодирования видео для моего приложения. (Обратите внимание, что изначально я пытался использоватьffmpeg-java, но у него есть несовместимые библиотеки)

Оригинальная проблема: Проблема, с которой я столкнулся, состоит в том, что я в настоящее время получаю каждый кадр какBitmap (просто равнинаandroid.graphics.Bitmap) и я не могу понять, как вставить это в кодировщик.

Решение вjavacv«sffmpeg: Используйте avpicture_fill (), формат от Android предположительно YUV420P, хотя я не могу проверить это, пока мои проблемы с кодировщиком (ниже) не будут решены.

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

Проблема сейчас: Строка, которая должна фактически кодировать данные, прерывает поток. Я получаю большую трассировку собственного стека кода, которую не могу понять. У кого-нибудь есть предложение?

Вот код, который я использую для создания экземпляров всехffmpeg библиотеки:

    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.");
    }

Это то, что я хочу иметь возможность выполнить дальше:

    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 + ")");

Но на данный момент я не знаю, как правильно разместить растровое изображение или правильно ли я его настроить.

Несколько замечаний по поводу кода: -VIDEO_WIDTH = 352 -VIDEO_HEIGHT = 288 -VIDEO_FPS = 30;

Ответы на вопрос(2)

Ваш ответ на вопрос