提交 ee3ba3fe 编写于 作者: Z Zhang Rui

ijksdl: implement YV12 picture copy to native window buffer

上级 baa26258
/*
* ijksdl_ffinc.h
* ffmpeg headers
*
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef IJKPLAYER__IJKSDL_FFINC_H
#define IJKPLAYER__IJKSDL_FFINC_H
#include "libavutil/imgutils.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#endif
...@@ -28,9 +28,6 @@ ...@@ -28,9 +28,6 @@
#include "ijksdl_mutex.h" #include "ijksdl_mutex.h"
#include "ijksdl_video.h" #include "ijksdl_video.h"
/* bpp=12, 8 bit Y plane followed by 8 bit 2x2 subsampled V and U planes.*/
#define SDL_FOURCC_PIX__YV12 0x32315659
typedef struct SDL_VoutOverlay_Opaque SDL_VoutOverlay_Opaque; typedef struct SDL_VoutOverlay_Opaque SDL_VoutOverlay_Opaque;
typedef struct SDL_VoutOverlay SDL_VoutOverlay; typedef struct SDL_VoutOverlay SDL_VoutOverlay;
typedef struct SDL_VoutOverlay { typedef struct SDL_VoutOverlay {
...@@ -50,8 +47,8 @@ typedef struct SDL_VoutOverlay { ...@@ -50,8 +47,8 @@ typedef struct SDL_VoutOverlay {
typedef struct SDL_VoutSurface_Opaque SDL_VoutSurface_Opaque; typedef struct SDL_VoutSurface_Opaque SDL_VoutSurface_Opaque;
typedef struct SDL_VoutSurface SDL_VoutSurface; typedef struct SDL_VoutSurface SDL_VoutSurface;
typedef struct SDL_VoutSurface { typedef struct SDL_VoutSurface {
int w; int w; /* width in pixels */
int h; int h; /* height in pixels */
Uint32 format; /* fourcc number */ Uint32 format; /* fourcc number */
SDL_VoutSurface_Opaque *opaque; SDL_VoutSurface_Opaque *opaque;
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <assert.h> #include <assert.h>
#include <android/native_window.h> #include <android/native_window.h>
#include "ijkutil/ijkutil.h"
#include "ijksdl_ffinc.h"
#include "ijksdl_vout.h" #include "ijksdl_vout.h"
#include "ijksdl_vout_internal.h" #include "ijksdl_vout_internal.h"
...@@ -61,27 +63,40 @@ static SDL_VoutSurface *vout_set_video_mode_l(SDL_Vout *vout, int w, int h, int ...@@ -61,27 +63,40 @@ static SDL_VoutSurface *vout_set_video_mode_l(SDL_Vout *vout, int w, int h, int
int curr_w = 0; int curr_w = 0;
int curr_h = 0; int curr_h = 0;
int curr_format = 0; int curr_format = 0;
int buf_w = (w + 1) & ~1;
int buf_h = (h + 1) & ~1;
assert(bpp == 0);
if (!native_window) if (!native_window)
return NULL; return NULL;
curr_w = ANativeWindow_getWidth(native_window); curr_w = ANativeWindow_getWidth(native_window);
curr_h = ANativeWindow_getHeight(native_window); curr_h = ANativeWindow_getHeight(native_window);
curr_format = ANativeWindow_getFormat(native_window); curr_format = ANativeWindow_getFormat(native_window);
if (curr_w == w && curr_h == h) { if (curr_w == buf_w && curr_h == buf_h) {
surface->w = w;
surface->h = h;
surface->format = curr_format; surface->format = curr_format;
return surface; return surface;
} }
ANativeWindow_setBuffersGeometry(native_window, w, h, curr_format); ALOGI("vout_set_video_mode_l (w:%d, h:%d, fmt:%d) => (w:%d, h:%d, fmt:%d)",
curr_w, curr_h, curr_format,
buf_w, buf_h, curr_format);
ANativeWindow_setBuffersGeometry(native_window, buf_w, buf_h, curr_format);
curr_w = ANativeWindow_getWidth(native_window); curr_w = ANativeWindow_getWidth(native_window);
curr_h = ANativeWindow_getHeight(native_window); curr_h = ANativeWindow_getHeight(native_window);
curr_format = ANativeWindow_getFormat(native_window); curr_format = ANativeWindow_getFormat(native_window);
if (curr_w == w && curr_h == h) { if (curr_w == buf_w && curr_h == buf_h) {
surface->w = w;
surface->h = h;
surface->format = curr_format; surface->format = curr_format;
return surface; return surface;
} }
ALOGE("vout_set_video_mode_l (w:%d, h:%d, fmt:%d) => (w:%d, h:%d, fmt:%d)",
curr_w, curr_h, curr_format,
buf_w, buf_h, curr_format);
return NULL; return NULL;
} }
...@@ -93,10 +108,122 @@ static SDL_VoutSurface *vout_set_video_mode(SDL_Vout *vout, int w, int h, int bp ...@@ -93,10 +108,122 @@ static SDL_VoutSurface *vout_set_video_mode(SDL_Vout *vout, int w, int h, int bp
return surface; return surface;
} }
static void vout_copy_image_yv12(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
{
assert(overlay->format == SDL_YV12_OVERLAY);
assert(overlay->planes == 3);
int min_height = IJKMIN(out_buffer->height, overlay->h);
int dst_y_pitch = out_buffer->stride;
int dst_c_pitch = IJKALIGN(out_buffer->stride / 2, 16);
int dst_y_size = dst_y_pitch * out_buffer->height;
int dst_c_size = dst_c_pitch * out_buffer->height / 2;
uint8_t *dst_pixels[] = {
out_buffer->bits,
out_buffer->bits + dst_y_size,
out_buffer->bits + dst_y_size + dst_c_size
};
uint8_t *dst_planes_size[] = { dst_y_size, dst_c_size, dst_c_size };
int dst_pitches[] = { dst_y_pitch, dst_c_pitch, dst_c_pitch };
for (int i = 0; i < 3; ++i) {
int dst_pitch = dst_pitches[i];
int src_pitch = overlay->pitches[i];
uint8_t *dst_pixels = dst_pixels[i];
const uint8_t *src_pixels = overlay->pixels[i];
int dst_plane_size = dst_planes_size[i];
if (dst_pitch == src_pitch) {
memcpy(dst_pixels, src_pixels, dst_plane_size);
} else {
int bytewidth = IJKMIN(dst_pitch, src_pitch);
av_image_copy_plane(dst_pixels, dst_pitch, src_pixels, src_pitch, bytewidth, min_height);
}
}
}
static int voud_display_overlay_l(SDL_Vout *vout, SDL_VoutOverlay *overlay)
{
SDL_Vout_Opaque *opaque = vout->opaque;
ANativeWindow *native_window = opaque->native_window;
int curr_w, curr_h, curr_format;
int retval;
if (!native_window)
return -1;
if (!overlay || overlay->w <= 0 || overlay->h <= 0)
return -1;
int buf_w = (overlay->w + 1) & ~1;
int buf_h = (overlay->h + 1) & ~1;
curr_w = ANativeWindow_getWidth(native_window);
curr_h = ANativeWindow_getHeight(native_window);
curr_format = ANativeWindow_getFormat(native_window);
if (curr_w != buf_w ||
curr_h != buf_h ||
curr_format != overlay->format) {
// correct w, h, format
ALOGI("vout_set_video_mode_l (w:%d, h:%d, fmt:%d) => (w:%d, h:%d, fmt:%d)",
curr_w, curr_h, curr_format,
buf_w, buf_h, overlay->format);
ANativeWindow_setBuffersGeometry(native_window, buf_w, buf_h, overlay->format);
curr_w = ANativeWindow_getWidth(native_window);
curr_h = ANativeWindow_getHeight(native_window);
curr_format = ANativeWindow_getFormat(native_window);
if (curr_w != buf_w ||
curr_h != buf_h ||
curr_format != overlay->format) {
ALOGE("unexpected native window (w:%d, h:%d, fmt:%d), expecting (w:%d, h:%d, fmt:%d)",
curr_w, curr_h, curr_format,
buf_w, buf_h, overlay->format);
return -1;
}
}
ANativeWindow_Buffer out_buffer;
retval = ANativeWindow_lock(native_window, &out_buffer, NULL);
if (retval < 0) {
ALOGE("voud_display_overlay_l: ANativeWindow_lock: failed %d", retval);
return retval;
}
if (out_buffer.width != buf_w || out_buffer.height != buf_w) {
ALOGE("unexpected native window buffer (w:%d, h:%d, fmt:%d), expecting (w:%d, h:%d, fmt:%d)",
out_buffer.width, out_buffer.height, out_buffer.format,
buf_w, buf_h, overlay->format);
return -1;
}
int copy_ret = 0;
switch (out_buffer.format) {
case SDL_YV12_OVERLAY:
vout_copy_image_yv12(&out_buffer, overlay);
break;
default:
ALOGE("voud_display_overlay_l: unexpected buffer format: %d", out_buffer.format);
copy_ret = -1;
break;
}
retval = ANativeWindow_unlockAndPost(native_window);
if (retval < 0) {
ALOGE("voud_display_overlay_l: ANativeWindow_unlockAndPost: failed %d", retval);
return retval;
}
return copy_ret;
}
static int voud_display_overlay(SDL_Vout *vout, SDL_VoutOverlay *overlay) static int voud_display_overlay(SDL_Vout *vout, SDL_VoutOverlay *overlay)
{ {
// FIXME: implement SDL_LockMutex(vout->mutex);
return -1; int retval = voud_display_overlay_l(vout, overlay);
SDL_UnlockMutex(vout->mutex);
return retval;
} }
SDL_Vout *SDL_VoutAndroid_CreateForANativeWindow() SDL_Vout *SDL_VoutAndroid_CreateForANativeWindow()
......
...@@ -23,8 +23,7 @@ ...@@ -23,8 +23,7 @@
#include "ijksdl_vout_ffmpeg.h" #include "ijksdl_vout_ffmpeg.h"
#include "libavcodec/avcodec.h" #include "ijksdl_ffinc.h"
#include "libswscale/swscale.h"
#include "ijksdl_mutex.h" #include "ijksdl_mutex.h"
#include "ijksdl_vout_internal.h" #include "ijksdl_vout_internal.h"
...@@ -39,6 +38,7 @@ typedef struct SDL_VoutOverlay_Opaque { ...@@ -39,6 +38,7 @@ typedef struct SDL_VoutOverlay_Opaque {
} SDL_VoutOverlay_Opaque; } SDL_VoutOverlay_Opaque;
/* Always assume a linesize alignment of 1 here */ /* Always assume a linesize alignment of 1 here */
// FIXME: alignment
static AVFrame *alloc_avframe(SDL_VoutOverlay_Opaque* opaque, enum AVPixelFormat format, int width, int height) static AVFrame *alloc_avframe(SDL_VoutOverlay_Opaque* opaque, enum AVPixelFormat format, int width, int height)
{ {
int frame_bytes = avpicture_get_size(format, width, height); int frame_bytes = avpicture_get_size(format, width, height);
...@@ -52,8 +52,9 @@ static AVFrame *alloc_avframe(SDL_VoutOverlay_Opaque* opaque, enum AVPixelFormat ...@@ -52,8 +52,9 @@ static AVFrame *alloc_avframe(SDL_VoutOverlay_Opaque* opaque, enum AVPixelFormat
return NULL; return NULL;
} }
AVPicture *pic = (AVPicture *) frame;
avcodec_get_frame_defaults(frame); avcodec_get_frame_defaults(frame);
avpicture_fill((AVPicture *) frame, frame_buf, format, width, height); avpicture_fill(pic, frame_buf, format, width, height);
opaque->frame_buf = frame_buf; opaque->frame_buf = frame_buf;
return frame; return frame;
} }
......
...@@ -31,4 +31,12 @@ ...@@ -31,4 +31,12 @@
#define IJKMAX(a, b) ((a) > (b) ? (a) : (b)) #define IJKMAX(a, b) ((a) > (b) ? (a) : (b))
#endif #endif
#ifndef IJKMIN
#define IJKMIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef IJKALIGN
#define IJKALIGN(x, align) ((( x ) + (align) - 1) / (align) * (align))
#endif
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册