int SDL_VoutFFmpeg_ConvertFrame(
    SDL_VoutOverlay *overlay, AVFrame *frame,
    struct SwsContext **p_sws_ctx, int sws_flags)
{
    assert(overlay);
    assert(p_sws_ctx);
    SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
    AVPicture dest_pic = { { 0 } };

    for (int i = 0; i < overlay->planes; ++i) {
        dest_pic.data[i] = overlay->pixels[i];
        dest_pic.linesize[i] = overlay->pitches[i];
    }

    av_frame_unref(opaque->linked_frame);

    int use_linked_frame = 0;
    enum AVPixelFormat dst_format = AV_PIX_FMT_NONE;
    switch (overlay->format) {
    case SDL_FCC_YV12:
        if (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUVJ420P) {
            // ALOGE("direct draw frame");
            use_linked_frame = 1;
            av_frame_ref(opaque->linked_frame, frame);
            overlay_fill(overlay, opaque->linked_frame, opaque->planes);
            FFSWAP(Uint8*, overlay->pixels[1], overlay->pixels[2]);
        } else {
예제 #2
0
int SDL_VoutFFmpeg_ConvertFrame(
    SDL_VoutOverlay *overlay, AVFrame *frame,
    struct SwsContext **p_sws_ctx, int sws_flags)
{
    assert(overlay);
    assert(p_sws_ctx);
    SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
    AVPicture dest_pic = { { 0 } };

    for (int i = 0; i < overlay->planes; ++i) {
        dest_pic.data[i] = overlay->pixels[i];
        dest_pic.linesize[i] = overlay->pitches[i];
    }

    av_frame_unref(opaque->linked_frame);

    int need_swap_uv = 0;
    int use_linked_frame = 0;
    enum AVPixelFormat dst_format = AV_PIX_FMT_NONE;
    switch (overlay->format) {
    case SDL_FCC_YV12:
        need_swap_uv = 1;
        // no break;
    case SDL_FCC_I420:
        if (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUVJ420P) {
            // ALOGE("direct draw frame");
            use_linked_frame = 1;
            av_frame_ref(opaque->linked_frame, frame);
            overlay_fill(overlay, opaque->linked_frame, opaque->planes);
        } else {
            // ALOGE("copy draw frame");
            overlay_fill(overlay, opaque->frame, opaque->planes);
            dest_pic.data[1] = overlay->pixels[1];
            dest_pic.data[2] = overlay->pixels[2];
            dst_format = AV_PIX_FMT_YUV420P;
        }

        if (need_swap_uv) {
            if (use_linked_frame) {
                FFSWAP(Uint8*, overlay->pixels[1], overlay->pixels[2]);
            } else {
                FFSWAP(Uint8*, dest_pic.data[1], dest_pic.data[2]);
            }
        }
        break;
    case SDL_FCC_RV32:
        overlay_fill(overlay, opaque->frame, opaque->planes);
        dst_format = AV_PIX_FMT_0BGR32;
        break;
    case SDL_FCC_RV24:
        overlay_fill(overlay, opaque->frame, opaque->planes);
        dst_format = AV_PIX_FMT_RGB24;
        break;
    case SDL_FCC_RV16:
        overlay_fill(overlay, opaque->frame, opaque->planes);
        dst_format = AV_PIX_FMT_RGB565;
        break;
    default:
        ALOGE("SDL_VoutFFmpeg_ConvertPicture: unexpected overlay format %s(%d)",
            (char*)&overlay->format, overlay->format);
        return -1;
    }
SDL_VoutOverlay *SDL_VoutFFmpeg_CreateOverlay(int width, int height, Uint32 format, SDL_Vout *display)
{
    SDLTRACE("SDL_VoutFFmpeg_CreateOverlay(w=%d, h=%d, fmt=%.4s(0x%x, dp=%p)",
        width, height, (const char*) &format, format, display);
    SDL_VoutOverlay *overlay = SDL_VoutOverlay_CreateInternal(sizeof(SDL_VoutOverlay_Opaque));
    if (!overlay) {
        ALOGE("overlay allocation failed");
        return NULL;
    }

    SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
    overlay->format = format;
    overlay->pitches = opaque->pitches;
    overlay->pixels = opaque->pixels;
    overlay->w = width;
    overlay->h = height;

    enum AVPixelFormat ff_format = AV_PIX_FMT_NONE;
    int buf_width = width;  // must be aligned to 16 bytes pitch for arm-neon image-convert
    int buf_height = height;
    switch (format) {
    case SDL_FCC_YV12: {
        ff_format = AV_PIX_FMT_YUV420P;
        buf_width = IJKALIGN(width, 16); // 1 bytes per pixel for Y-plane
        opaque->planes = 3;
        break;
    }
    case SDL_FCC_RV16: {
        ff_format = AV_PIX_FMT_RGB565;
        buf_width = IJKALIGN(width, 8); // 2 bytes per pixel
        opaque->planes = 1;
        break;
    }
    case SDL_FCC_RV32: {
        ff_format = AV_PIX_FMT_0BGR32;
        buf_width = IJKALIGN(width, 4); // 4 bytes per pixel
        opaque->planes = 1;
        break;
    }
    default:
        ALOGE("SDL_VoutFFmpeg_CreateOverlay(...): unknown format %.4s(0x%x)", (char*)&format, format);
        goto fail;
    }

    opaque->frame = alloc_avframe(opaque, ff_format, buf_width, buf_height);
    if (!opaque->frame) {
        ALOGE("overlay->opaque->frame allocation failed");
        goto fail;
    }
    opaque->mutex = SDL_CreateMutex();
    overlay_fill(overlay, opaque->frame, opaque->planes);

    overlay->free_l = overlay_free_l;
    overlay->lock = overlay_lock;
    overlay->unlock = overlay_unlock;

    return overlay;

    fail:
    overlay_free_l(overlay);
    return NULL;
}
예제 #4
0
SDL_VoutOverlay *SDL_VoutFFmpeg_CreateOverlay(int width, int height, Uint32 format, SDL_Vout *display)
{
    SDLTRACE("SDL_VoutFFmpeg_CreateOverlay(w=%d, h=%d, fmt=%.4s(0x%x, dp=%p)",
        width, height, (const char*) &format, format, display);
    SDL_VoutOverlay *overlay = SDL_VoutOverlay_CreateInternal(sizeof(SDL_VoutOverlay_Opaque));
    if (!overlay) {
        ALOGE("overlay allocation failed");
        return NULL;
    }

    SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
    overlay->format = format;
    overlay->pitches = opaque->pitches;
    overlay->pixels = opaque->pixels;
    overlay->w = width;
    overlay->h = height;

    enum AVPixelFormat ff_format = AV_PIX_FMT_NONE;
    int buf_width = width;
    int buf_height = height;
    switch (format) {
    case SDL_FCC_I420:
    case SDL_FCC_YV12: {
        ff_format = AV_PIX_FMT_YUV420P;
        // FIXME: need runtime config
#if defined(__ANDROID__)
        // 16 bytes align pitch for arm-neon image-convert
        buf_width = IJKALIGN(width, 16); // 1 bytes per pixel for Y-plane
#elif defined(__APPLE__)
        // 2^n align for width
        buf_width = width;
        if (width > 0)
            buf_width = 1 << (sizeof(int) * 8 - __builtin_clz(width));
#else
        buf_width = IJKALIGN(width, 16); // unknown platform
#endif
        opaque->planes = 3;
        break;
    }
    case SDL_FCC_RV16: {
        ff_format = AV_PIX_FMT_RGB565;
        buf_width = IJKALIGN(width, 8); // 2 bytes per pixel
        opaque->planes = 1;
        break;
    }
    case SDL_FCC_RV24: {
        ff_format = AV_PIX_FMT_RGB24;
#if defined(__ANDROID__)
        // 16 bytes align pitch for arm-neon image-convert
        buf_width = IJKALIGN(width, 16); // 1 bytes per pixel for Y-plane
#elif defined(__APPLE__)
        buf_width = width;
#else
        buf_width = IJKALIGN(width, 16); // unknown platform
#endif
        opaque->planes = 1;
        break;
    }
    case SDL_FCC_RV32: {
        ff_format = AV_PIX_FMT_0BGR32;
        buf_width = IJKALIGN(width, 4); // 4 bytes per pixel
        opaque->planes = 1;
        break;
    }
    default:
        ALOGE("SDL_VoutFFmpeg_CreateOverlay(...): unknown format %.4s(0x%x)", (char*)&format, format);
        goto fail;
    }

    opaque->frame = alloc_avframe(opaque, ff_format, buf_width, buf_height);
    if (!opaque->frame) {
        ALOGE("overlay->opaque->frame allocation failed");
        goto fail;
    }
    opaque->mutex = SDL_CreateMutex();
    overlay_fill(overlay, opaque->frame, opaque->planes);

    overlay->free_l = overlay_free_l;
    overlay->lock = overlay_lock;
    overlay->unlock = overlay_unlock;

    return overlay;

    fail:
    overlay_free_l(overlay);
    return NULL;
}