Search code examples
androidandroid-ndkh.264android-mediacodec

Any way to render a raw video on a ANativeWindow and at the same time write it to a file?


I try to render a raw h264 video to a surface (after decoding) and write it at the same time to a file. The rendering is working fine but when I want to get the current output buffer, it always have a size of 8 and the output file have a size of 3,87 Ko.

It seems like the output buffer is locked by the surface (ANativeWindow)? Anyone can give me an advice to do it without creating another codec?

The codec is configured with an output surface :

 if (AMEDIA_OK == AMediaCodec_configure(d->codec, d->format, d->window /*the native window */, NULL, 0)

Here is the code snipet when I try to get the output buffer :

if (!d->sawOutputEOS) {
    AMediaCodecBufferInfo info;
    auto status = AMediaCodec_dequeueOutputBuffer(d->codec, &info, -1);
    if (status >= 0) {
        if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
            LOGV("output EOS");
            d->sawOutputEOS = true;
            d->isPlaying = false;
        }
        int64_t delay = 333000;
        usleep((useconds_t )delay / 15);
        size_t size;
        // here i get the output buffer
        uint8_t *outputbuffer = AMediaCodec_getOutputBuffer(d->codec,status,&size);
        write(d->fd1,outputbuffer,size); // the output is always 0
        LOGV("%d",size); // the size is always 8
        LOGV("FRAME num : %d", counter[d->nb]++);
        AMediaCodec_releaseOutputBuffer(d->codec, status, info.size != 0);
        if (d->renderonce) {
            d->renderonce = false;
            return;
        }
    } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
        LOGV("output buffers changed");
    } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
        auto format = AMediaCodec_getOutputFormat(d->codec);
        LOGV("format changed to: %s", AMediaFormat_toString(format));
        AMediaFormat_delete(format);
        d->formatChanged = true;
    } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
        LOGV("no output buffer right now");
    } else {
        LOGV("unexpected info code: %zd", status);
    }
}

Thanks in advance


Solution

  • It's not locked; you asked the decoder to work for display, so it used the fastest route to display, without exposing the pixels to readable memory. You may find that the format is the opaque COLOR_FormatSurface, as explained here.