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 {
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; }
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; }