745 lines
22 KiB
C
745 lines
22 KiB
C
/*
|
|
* This file is part of libbluray
|
|
* Copyright (C) 2010 William Hahne
|
|
* Copyright (C) 2012-2014 Petri Hintukainen <phintuka@users.sourceforge.net>
|
|
*
|
|
* This library 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.
|
|
*
|
|
* This library 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.s
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#if HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "bdjo.h"
|
|
#include "util.h"
|
|
|
|
#include "bdj/bdjo_parse.h"
|
|
|
|
#include "bluray.h"
|
|
#include "bluray_internal.h"
|
|
#include "decoders/overlay.h"
|
|
#include "disc/disc.h"
|
|
|
|
#include "file/file.h"
|
|
#include "util/logging.h"
|
|
#include "util/macro.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
|
|
/* this automatically generated header is included to cross-check native function signatures */
|
|
#include "org_videolan_Libbluray.h"
|
|
|
|
/* Disable some warnings */
|
|
#if defined __GNUC__
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
#define CPP_EXTERN extern
|
|
#else
|
|
#define CPP_EXTERN
|
|
#endif
|
|
|
|
/*
|
|
* build org.videolan.TitleInfo
|
|
*/
|
|
|
|
static jobject _make_title_info(JNIEnv* env, const BLURAY_TITLE *title, int title_number)
|
|
{
|
|
jobject ti = NULL;
|
|
if (title) {
|
|
int title_type = title->bdj ? 2 : 1;
|
|
int playback_type = (!!title->interactive) + ((!!title->bdj) << 1);
|
|
ti = bdj_make_object(env, "org/videolan/TitleInfo",
|
|
"(IIII)V",
|
|
(jint)title_number, (jint)title_type, (jint)playback_type, (jint)title->id_ref);
|
|
}
|
|
return ti;
|
|
}
|
|
|
|
static jobjectArray _make_title_infos(JNIEnv * env, const BLURAY_DISC_INFO *disc_info)
|
|
{
|
|
jobjectArray titleArr = bdj_make_array(env, "org/videolan/TitleInfo", disc_info->num_titles + 2);
|
|
jobject titleInfo;
|
|
|
|
if (!titleArr) {
|
|
return NULL;
|
|
}
|
|
|
|
for (unsigned i = 0; i <= disc_info->num_titles; i++) {
|
|
titleInfo = _make_title_info(env, disc_info->titles[i], i);
|
|
(*env)->SetObjectArrayElement(env, titleArr, i, titleInfo);
|
|
}
|
|
|
|
titleInfo = _make_title_info(env, disc_info->first_play, 65535);
|
|
(*env)->SetObjectArrayElement(env, titleArr, disc_info->num_titles + 1, titleInfo);
|
|
|
|
return titleArr;
|
|
}
|
|
|
|
/*
|
|
* build org.videolan.PlaylistInfo
|
|
*/
|
|
|
|
static jobjectArray _make_stream_array(JNIEnv* env, int count, BLURAY_STREAM_INFO* streams)
|
|
{
|
|
jobjectArray streamArr = bdj_make_array(env,
|
|
"org/videolan/StreamInfo", count);
|
|
|
|
if (!streamArr) {
|
|
return NULL;
|
|
}
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
BLURAY_STREAM_INFO s = streams[i];
|
|
jstring lang = (*env)->NewStringUTF(env, (char*)s.lang);
|
|
jobject streamObj = bdj_make_object(env,
|
|
"org/videolan/StreamInfo",
|
|
"(BBBCLjava/lang/String;BB)V",
|
|
(jbyte)s.coding_type, (jbyte)s.format,
|
|
(jbyte)s.rate, (jchar)s.char_code,
|
|
lang,
|
|
(jbyte)s.aspect, (jbyte)s.subpath_id);
|
|
(*env)->SetObjectArrayElement(env, streamArr, i, streamObj);
|
|
}
|
|
|
|
return streamArr;
|
|
}
|
|
|
|
static jobject _make_playlist_info(JNIEnv* env, BLURAY_TITLE_INFO* ti)
|
|
{
|
|
jobjectArray marks = bdj_make_array(env, "org/videolan/TIMark",
|
|
ti->mark_count);
|
|
|
|
if (marks) {
|
|
for (uint32_t i = 0; i < ti->mark_count; i++) {
|
|
BLURAY_TITLE_MARK m = ti->marks[i];
|
|
jobject mark = bdj_make_object(env,
|
|
"org/videolan/TIMark",
|
|
"(IIJJJI)V",
|
|
(jint)m.idx, (jint)m.type, (jlong)m.start, (jlong)m.duration,
|
|
(jlong)m.offset, (jint)m.clip_ref);
|
|
(*env)->SetObjectArrayElement(env, marks, i, mark);
|
|
}
|
|
}
|
|
|
|
jobjectArray clips = bdj_make_array(env, "org/videolan/TIClip",
|
|
ti->clip_count);
|
|
|
|
if (clips) {
|
|
for (uint32_t i = 0; i < ti->clip_count; i++) {
|
|
BLURAY_CLIP_INFO info = ti->clips[i];
|
|
|
|
jobjectArray videoStreams = _make_stream_array(env, info.video_stream_count,
|
|
info.video_streams);
|
|
|
|
jobjectArray audioStreams = _make_stream_array(env, info.audio_stream_count,
|
|
info.audio_streams);
|
|
|
|
jobjectArray pgStreams = _make_stream_array(env, info.pg_stream_count,
|
|
info.pg_streams);
|
|
|
|
jobjectArray igStreams = _make_stream_array(env, info.ig_stream_count,
|
|
info.ig_streams);
|
|
|
|
jobjectArray secVideoStreams = _make_stream_array(env, info.sec_video_stream_count,
|
|
info.sec_video_streams);
|
|
|
|
jobjectArray secAudioStreams = _make_stream_array(env, info.sec_audio_stream_count,
|
|
info.sec_audio_streams);
|
|
|
|
jobject clip = bdj_make_object(env,
|
|
"org/videolan/TIClip",
|
|
"(I[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;)V",
|
|
(jint)i, videoStreams, audioStreams, pgStreams, igStreams, secVideoStreams, secAudioStreams);
|
|
|
|
(*env)->SetObjectArrayElement(env, clips, i, clip);
|
|
}
|
|
}
|
|
|
|
return bdj_make_object(env,
|
|
"org/videolan/PlaylistInfo",
|
|
"(IJI[Lorg/videolan/TIMark;[Lorg/videolan/TIClip;)V",
|
|
(jint)ti->playlist, (jlong)ti->duration, (jint)ti->angle_count,
|
|
marks, clips);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
JNIEXPORT jobjectArray JNICALL Java_org_videolan_Libbluray_getTitleInfosN
|
|
(JNIEnv * env, jclass cls, jlong np)
|
|
{
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
const BLURAY_DISC_INFO *disc_info;
|
|
|
|
BD_DEBUG(DBG_JNI, "getTitleInfosN()\n");
|
|
|
|
disc_info = bd_get_disc_info(bd);
|
|
|
|
return _make_title_infos(env, disc_info);
|
|
}
|
|
|
|
JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getPlaylistInfoN
|
|
(JNIEnv * env, jclass cls, jlong np, jint playlist)
|
|
{
|
|
BLURAY *bd = (BLURAY*)(intptr_t)np;
|
|
BLURAY_TITLE_INFO* ti;
|
|
|
|
BD_DEBUG(DBG_JNI, "getPlaylistInfoN(%d)\n", (int)playlist);
|
|
|
|
ti = bd_get_playlist_info(bd, playlist, 0);
|
|
if (!ti)
|
|
return NULL;
|
|
|
|
jobject titleInfo = _make_playlist_info(env, ti);
|
|
|
|
bd_free_title_info(ti);
|
|
|
|
return titleInfo;
|
|
}
|
|
|
|
JNIEXPORT jbyteArray JNICALL Java_org_videolan_Libbluray_getAacsDataN
|
|
(JNIEnv * env, jclass cls, jlong np, jint type)
|
|
{
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
const uint8_t *data = bd_get_aacs_data(bd, type);
|
|
size_t data_size = 16;
|
|
|
|
BD_DEBUG(DBG_JNI, "getAacsDataN(%d) -> %p\n", (int)type, (const void *)data);
|
|
|
|
if (!data) {
|
|
return NULL;
|
|
}
|
|
if (type == 1/*BD_AACS_DISC_ID*/) {
|
|
data_size = 20;
|
|
}
|
|
if (type == 7/*BD_AACS_CONTENT_CERT_ID*/) {
|
|
data_size = 6;
|
|
}
|
|
if (type == 8/*BD_AACS_BDJ_ROOT_CERT_HASH*/) {
|
|
data_size = 20;
|
|
}
|
|
if (type == 0x1000/*BD_BDPLUS_TYPE*/) {
|
|
data_size = strlen((const char*)data);
|
|
}
|
|
|
|
jbyteArray array = (*env)->NewByteArray(env, data_size);
|
|
(*env)->SetByteArrayRegion(env, array, 0, data_size, (const jbyte *)data);
|
|
return array;
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_getUOMaskN(JNIEnv * env,
|
|
jclass cls, jlong np) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
BD_DEBUG(DBG_JNI, "getUOMaskN()\n");
|
|
return bd_get_uo_mask(bd);
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_org_videolan_Libbluray_setUOMaskN(JNIEnv * env,
|
|
jclass cls, jlong np, jboolean menuCallMask, jboolean titleSearchMask) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
BD_DEBUG(DBG_JNI, "setUOMaskN(%d,%d)\n", (int)menuCallMask, (int)titleSearchMask);
|
|
bd_set_bdj_uo_mask(bd, ((!!menuCallMask) * BDJ_MENU_CALL_MASK) | ((!!titleSearchMask) * BDJ_TITLE_SEARCH_MASK));
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_org_videolan_Libbluray_setKeyInterestN(JNIEnv * env,
|
|
jclass cls, jlong np, jint mask) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
BD_DEBUG(DBG_JNI, "setKeyInterestN(0x%x)\n", (int)mask);
|
|
bd_set_bdj_kit(bd, mask);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_setVirtualPackageN(JNIEnv * env,
|
|
jclass cls, jlong np, jstring vpPath, jboolean psr_init_backup) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
const char *path = NULL;
|
|
jint result;
|
|
|
|
if (vpPath) {
|
|
path = (*env)->GetStringUTFChars(env, vpPath, NULL);
|
|
}
|
|
|
|
BD_DEBUG(DBG_JNI|DBG_CRIT, "setVirtualPackageN(%s,%d)\n", path ? path : "<null>", (int)psr_init_backup);
|
|
|
|
result = bd_set_virtual_package(bd, path, (int)psr_init_backup);
|
|
|
|
if (vpPath) {
|
|
(*env)->ReleaseStringUTFChars(env, vpPath, path);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekN(JNIEnv * env,
|
|
jclass cls, jlong np, jint playitem, jint playmark, jlong tick) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
BD_DEBUG(DBG_JNI, "seekN(tick=%"PRId64", mark=%d, playitem=%d)\n", (int64_t)tick, (int)playmark, (int)playitem);
|
|
|
|
return bd_bdj_seek(bd, playitem, playmark, tick);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectPlaylistN(
|
|
JNIEnv * env, jclass cls, jlong np, jint playlist, jint playitem, jint playmark, jlong time) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
if (!bd) {
|
|
return 0;
|
|
}
|
|
|
|
BD_DEBUG(DBG_JNI, "selectPlaylistN(pl=%d, pi=%d, pm=%d, time=%ld)\n",
|
|
(int)playlist, (int)playitem, (int)playmark, (long)time);
|
|
|
|
return bd_play_playlist_at(bd, playlist, playitem, playmark, time);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectTitleN(JNIEnv * env,
|
|
jclass cls, jlong np, jint title) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
BD_DEBUG(DBG_JNI, "selectTitleN(%d)\n", (int)title);
|
|
|
|
return bd_play_title_internal(bd, title);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectAngleN(JNIEnv * env,
|
|
jclass cls, jlong np, jint angle) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
return bd_select_angle(bd, angle - 1);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_soundEffectN(JNIEnv * env,
|
|
jclass cls, jlong np, jint id) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
return bd_bdj_sound_effect(bd, id);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_tellTimeN(JNIEnv * env,
|
|
jclass cls, jlong np) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
return bd_tell_time(bd);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectRateN(JNIEnv * env,
|
|
jclass cls, jlong np, jfloat rate, jint reason) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
BD_DEBUG(DBG_JNI, "selectRateN(%1.1f, %d)\n", (float)rate, (int)reason);
|
|
|
|
bd_select_rate(bd, (float)rate, reason);
|
|
return 1;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_readRegN(JNIEnv * env,
|
|
jclass cls, jlong np, jint is_psr, jint num) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
int value = bd_reg_read(bd, is_psr, num);
|
|
|
|
BD_DEBUG(DBG_JNI, "readRegN(%s_%d) -> %d\n", is_psr ? "PSR" : "GPR", (int)num, (int)value);
|
|
|
|
return value;
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_writeRegN(JNIEnv * env,
|
|
jclass cls, jlong np, jint is_psr, jint num, jint value, jint mask) {
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
if ((uint32_t)mask == 0xffffffff) {
|
|
BD_DEBUG(DBG_JNI, "writeRegN(%s_%d,%d)\n",
|
|
is_psr ? "PSR" : "GPR", (int)num, (int)value);
|
|
} else {
|
|
BD_DEBUG(DBG_JNI, "writeRegN(%s_%d,0x%x,0x%08x)\n",
|
|
is_psr ? "PSR" : "GPR", (int)num, (int)value, (int)mask);
|
|
}
|
|
|
|
return bd_reg_write(bd, is_psr, num, value, mask);
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_cacheBdRomFileN(JNIEnv * env,
|
|
jclass cls, jlong np,
|
|
jstring jrel_path, jstring jcache_path) {
|
|
|
|
BLURAY *bd = (BLURAY*)(intptr_t)np;
|
|
BD_DISC *disc = bd_get_disc(bd);
|
|
int result = -1;
|
|
|
|
const char *rel_path = (*env)->GetStringUTFChars(env, jrel_path, NULL);
|
|
const char *cache_path = (*env)->GetStringUTFChars(env, jcache_path, NULL);
|
|
if (!rel_path || !cache_path) {
|
|
BD_DEBUG(DBG_JNI | DBG_CRIT, "cacheBdRomFile() failed: no path\n");
|
|
goto out;
|
|
}
|
|
BD_DEBUG(DBG_JNI, "cacheBdRomFile(%s => %s)\n", rel_path, cache_path);
|
|
|
|
result = disc_cache_bdrom_file(disc, rel_path, cache_path);
|
|
|
|
out:
|
|
if (rel_path) {
|
|
(*env)->ReleaseStringUTFChars(env, jrel_path, rel_path);
|
|
}
|
|
if (cache_path) {
|
|
(*env)->ReleaseStringUTFChars(env, jcache_path, cache_path);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
JNIEXPORT jobjectArray JNICALL Java_org_videolan_Libbluray_listBdFilesN(JNIEnv * env,
|
|
jclass cls, jlong np, jstring jpath,
|
|
jboolean onlyBdRom) {
|
|
|
|
BLURAY *bd = (BLURAY*)(intptr_t)np;
|
|
BD_DISC *disc = bd_get_disc(bd);
|
|
|
|
const char *path = (*env)->GetStringUTFChars(env, jpath, NULL);
|
|
if (!path) {
|
|
BD_DEBUG(DBG_JNI | DBG_CRIT, "listBdFilesN() failed: no path\n");
|
|
return NULL;
|
|
}
|
|
BD_DEBUG(DBG_JNI, "listBdFilesN(%s)\n", path);
|
|
|
|
/* open directory stream */
|
|
BD_DIR_H *dp;
|
|
if (onlyBdRom) {
|
|
dp = disc_open_bdrom_dir(disc, path);
|
|
} else {
|
|
dp = disc_open_dir(disc, path);
|
|
}
|
|
if (!dp) {
|
|
BD_DEBUG(DBG_JNI, "failed opening directory %s\n", path);
|
|
(*env)->ReleaseStringUTFChars(env, jpath, path);
|
|
return NULL;
|
|
}
|
|
(*env)->ReleaseStringUTFChars(env, jpath, path);
|
|
|
|
/* count files and create java strings (java array size must be known when it is created) */
|
|
jstring *files = NULL;
|
|
unsigned count = 0;
|
|
unsigned allocated = 0;
|
|
BD_DIRENT ent;
|
|
while (!dir_read(dp, &ent)) {
|
|
if (strcmp(ent.d_name, ".") && strcmp(ent.d_name, "..")) {
|
|
if (allocated <= count) {
|
|
allocated += 512;
|
|
jstring *tmp = realloc(files, sizeof(*files) * allocated);
|
|
if (!tmp) {
|
|
BD_DEBUG(DBG_JNI | DBG_CRIT, "failed allocating memory for %u directory entries\n", allocated);
|
|
break;
|
|
}
|
|
files = tmp;
|
|
}
|
|
files[count] = (*env)->NewStringUTF(env, ent.d_name);
|
|
count++;
|
|
}
|
|
}
|
|
dir_close(dp);
|
|
|
|
/* allocate java array */
|
|
jobjectArray arr = bdj_make_array(env, "java/lang/String", count);
|
|
if (!arr) {
|
|
BD_DEBUG(DBG_JNI | DBG_CRIT, "failed creating array [%d]\n", count);
|
|
} else {
|
|
/* populate files to array */
|
|
unsigned ii;
|
|
for (ii = 0; ii < count; ii++) {
|
|
(*env)->SetObjectArrayElement(env, arr, ii, files[ii]);
|
|
}
|
|
}
|
|
|
|
X_FREE(files);
|
|
|
|
return arr;
|
|
}
|
|
|
|
|
|
JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getBdjoN(JNIEnv * env,
|
|
jclass cls, jlong np, jstring jfile) {
|
|
|
|
BLURAY *bd = (BLURAY*)(intptr_t)np;
|
|
struct bdjo_data *bdjo;
|
|
jobject jbdjo = NULL;
|
|
|
|
const char *file = (*env)->GetStringUTFChars(env, jfile, NULL);
|
|
if (!file) {
|
|
BD_DEBUG(DBG_JNI | DBG_CRIT, "getBdjoN() failed: no path\n");
|
|
return NULL;
|
|
}
|
|
BD_DEBUG(DBG_JNI, "getBdjoN(%s)\n", file);
|
|
|
|
bdjo = bdjo_get(bd_get_disc(bd), file);
|
|
if (bdjo) {
|
|
jbdjo = bdjo_make_jobj(env, bdjo);
|
|
bdjo_free(&bdjo);
|
|
} else {
|
|
BD_DEBUG(DBG_JNI | DBG_CRIT, "getBdjoN(%s) failed\n", file);
|
|
}
|
|
|
|
(*env)->ReleaseStringUTFChars(env, jfile, file);
|
|
|
|
return jbdjo;
|
|
}
|
|
|
|
static void _updateGraphic(JNIEnv * env,
|
|
BLURAY *bd, jint width, jint height, jintArray rgbArray,
|
|
jint x0, jint y0, jint x1, jint y1,
|
|
BD_ARGB_BUFFER *buf) {
|
|
|
|
/* close ? */
|
|
if (!rgbArray) {
|
|
bd_bdj_osd_cb(bd, NULL, (int)width, (int)height, 0, 0, 0, 0);
|
|
return;
|
|
}
|
|
|
|
if (buf) {
|
|
|
|
/* copy to application-allocated buffer */
|
|
|
|
jint y, *dst;
|
|
jsize offset;
|
|
|
|
/* set dirty area before lock() */
|
|
buf->dirty[BD_OVERLAY_IG].x0 = (uint16_t)x0;
|
|
buf->dirty[BD_OVERLAY_IG].x1 = (uint16_t)x1;
|
|
buf->dirty[BD_OVERLAY_IG].y0 = (uint16_t)y0;
|
|
buf->dirty[BD_OVERLAY_IG].y1 = (uint16_t)y1;
|
|
|
|
/* get buffer */
|
|
if (buf->lock) {
|
|
buf->lock(buf);
|
|
}
|
|
if (!buf->buf[BD_OVERLAY_IG]) {
|
|
BD_DEBUG(DBG_BDJ | DBG_CRIT, "ARGB frame buffer missing\n");
|
|
if (buf->unlock) {
|
|
buf->unlock(buf);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* check buffer size */
|
|
|
|
if (buf->width < width || buf->height < height) {
|
|
/* assume buffer is only for the dirty arrea */
|
|
BD_DEBUG(DBG_BDJ, "ARGB frame buffer size is smaller than BD-J frame buffer size (app: %dx%d BD-J: %ldx%ld)\n",
|
|
buf->width, buf->height, (long)width, (long)height);
|
|
|
|
if (buf->width < (x1 - x0 + 1) || buf->height < (y1 - y0 + 1)) {
|
|
BD_DEBUG(DBG_BDJ | DBG_CRIT, "ARGB frame buffer size is smaller than dirty area\n");
|
|
if (buf->unlock) {
|
|
buf->unlock(buf);
|
|
}
|
|
return;
|
|
}
|
|
|
|
dst = (jint*)buf->buf[BD_OVERLAY_IG];
|
|
|
|
} else {
|
|
|
|
dst = (jint*)buf->buf[BD_OVERLAY_IG] + y0 * buf->width + x0;
|
|
|
|
/* clip */
|
|
if (y1 >= buf->height) {
|
|
BD_DEBUG(DBG_BDJ | DBG_CRIT, "Cropping %ld rows from bottom\n", (long)(y1 - buf->height));
|
|
y1 = buf->height - 1;
|
|
}
|
|
if (x1 >= buf->width) {
|
|
BD_DEBUG(DBG_BDJ | DBG_CRIT, "Cropping %ld pixels from right\n", (long)(x1 - buf->width));
|
|
x1 = buf->width - 1;
|
|
}
|
|
}
|
|
|
|
/* copy */
|
|
|
|
offset = y0 * width + x0;
|
|
|
|
for (y = y0; y <= y1; y++) {
|
|
(*env)->GetIntArrayRegion(env, rgbArray, offset, x1 - x0 + 1, dst);
|
|
offset += width;
|
|
dst += buf->width;
|
|
}
|
|
|
|
/* check for errors */
|
|
if ((*env)->ExceptionOccurred(env)) {
|
|
BD_DEBUG(DBG_BDJ | DBG_CRIT, "Array access error at %ld (+%ld)\n", (long)offset, (long)(x1 - x0 + 1));
|
|
(*env)->ExceptionDescribe(env);
|
|
(*env)->ExceptionClear(env);
|
|
}
|
|
|
|
if (buf->unlock) {
|
|
buf->unlock(buf);
|
|
}
|
|
|
|
bd_bdj_osd_cb(bd, buf->buf[BD_OVERLAY_IG], (int)width, (int)height,
|
|
x0, y0, x1, y1);
|
|
|
|
} else {
|
|
|
|
/* return java array */
|
|
|
|
jint *image = (jint *)(*env)->GetPrimitiveArrayCritical(env, rgbArray, NULL);
|
|
if (image) {
|
|
bd_bdj_osd_cb(bd, (const unsigned *)image, (int)width, (int)height,
|
|
x0, y0, x1, y1);
|
|
(*env)->ReleasePrimitiveArrayCritical(env, rgbArray, image, JNI_ABORT);
|
|
} else {
|
|
BD_DEBUG(DBG_BDJ | DBG_CRIT, "GetPrimitiveArrayCritical() failed\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
JNIEXPORT void JNICALL Java_org_videolan_Libbluray_updateGraphicN(JNIEnv * env,
|
|
jclass cls, jlong np, jint width, jint height, jintArray rgbArray,
|
|
jint x0, jint y0, jint x1, jint y1) {
|
|
|
|
BLURAY* bd = (BLURAY*)(intptr_t)np;
|
|
|
|
BD_DEBUG(DBG_JNI, "updateGraphicN(%ld,%ld-%ld,%ld)\n", (long)x0, (long)y0, (long)x1, (long)y1);
|
|
|
|
/* app callback not initialized ? */
|
|
if (!bd) {
|
|
return;
|
|
}
|
|
|
|
/* nothing to draw ? */
|
|
if (rgbArray && (x1 < x0 || y1 < y0 || (x1 | y1) < 0)) {
|
|
return;
|
|
}
|
|
|
|
BD_ARGB_BUFFER *buf = bd_lock_osd_buffer(bd);
|
|
|
|
_updateGraphic(env, bd, width, height, rgbArray, x0, y0, x1, y1, buf);
|
|
|
|
bd_unlock_osd_buffer(bd);
|
|
}
|
|
|
|
#define CC (char*)(uintptr_t) /* cast a literal from (const char*) */
|
|
#define VC (void*)(uintptr_t) /* cast function pointer to void* */
|
|
|
|
BD_PRIVATE CPP_EXTERN const JNINativeMethod
|
|
Java_org_videolan_Libbluray_methods[] =
|
|
{ /* AUTOMATICALLY GENERATED */
|
|
{
|
|
CC("getAacsDataN"),
|
|
CC("(JI)[B"),
|
|
VC(Java_org_videolan_Libbluray_getAacsDataN),
|
|
},
|
|
{
|
|
CC("getUOMaskN"),
|
|
CC("(J)J"),
|
|
VC(Java_org_videolan_Libbluray_getUOMaskN),
|
|
},
|
|
{
|
|
CC("setUOMaskN"),
|
|
CC("(JZZ)V"),
|
|
VC(Java_org_videolan_Libbluray_setUOMaskN),
|
|
},
|
|
{
|
|
CC("setKeyInterestN"),
|
|
CC("(JI)V"),
|
|
VC(Java_org_videolan_Libbluray_setKeyInterestN),
|
|
},
|
|
{
|
|
CC("getTitleInfosN"),
|
|
CC("(J)[Lorg/videolan/TitleInfo;"),
|
|
VC(Java_org_videolan_Libbluray_getTitleInfosN),
|
|
},
|
|
{
|
|
CC("getPlaylistInfoN"),
|
|
CC("(JI)Lorg/videolan/PlaylistInfo;"),
|
|
VC(Java_org_videolan_Libbluray_getPlaylistInfoN),
|
|
},
|
|
{
|
|
CC("seekN"),
|
|
CC("(JIIJ)J"),
|
|
VC(Java_org_videolan_Libbluray_seekN),
|
|
},
|
|
{
|
|
CC("selectPlaylistN"),
|
|
CC("(JIIIJ)I"),
|
|
VC(Java_org_videolan_Libbluray_selectPlaylistN),
|
|
},
|
|
{
|
|
CC("selectTitleN"),
|
|
CC("(JI)I"),
|
|
VC(Java_org_videolan_Libbluray_selectTitleN),
|
|
},
|
|
{
|
|
CC("setVirtualPackageN"),
|
|
CC("(JLjava/lang/String;Z)I"),
|
|
VC(Java_org_videolan_Libbluray_setVirtualPackageN),
|
|
},
|
|
{
|
|
CC("selectAngleN"),
|
|
CC("(JI)I"),
|
|
VC(Java_org_videolan_Libbluray_selectAngleN),
|
|
},
|
|
{
|
|
CC("soundEffectN"),
|
|
CC("(JI)I"),
|
|
VC(Java_org_videolan_Libbluray_soundEffectN),
|
|
},
|
|
{
|
|
CC("tellTimeN"),
|
|
CC("(J)J"),
|
|
VC(Java_org_videolan_Libbluray_tellTimeN),
|
|
},
|
|
{
|
|
CC("selectRateN"),
|
|
CC("(JFI)I"),
|
|
VC(Java_org_videolan_Libbluray_selectRateN),
|
|
},
|
|
{
|
|
CC("writeRegN"),
|
|
CC("(JIIII)I"),
|
|
VC(Java_org_videolan_Libbluray_writeRegN),
|
|
},
|
|
{
|
|
CC("readRegN"),
|
|
CC("(JII)I"),
|
|
VC(Java_org_videolan_Libbluray_readRegN),
|
|
},
|
|
{
|
|
CC("cacheBdRomFileN"),
|
|
CC("(JLjava/lang/String;Ljava/lang/String;)I"),
|
|
VC(Java_org_videolan_Libbluray_cacheBdRomFileN),
|
|
},
|
|
{
|
|
CC("listBdFilesN"),
|
|
CC("(JLjava/lang/String;Z)[Ljava/lang/String;"),
|
|
VC(Java_org_videolan_Libbluray_listBdFilesN),
|
|
},
|
|
{
|
|
CC("getBdjoN"),
|
|
CC("(JLjava/lang/String;)Lorg/videolan/bdjo/Bdjo;"),
|
|
VC(Java_org_videolan_Libbluray_getBdjoN),
|
|
},
|
|
{
|
|
CC("updateGraphicN"),
|
|
CC("(JII[IIIII)V"),
|
|
VC(Java_org_videolan_Libbluray_updateGraphicN),
|
|
},
|
|
};
|
|
|
|
BD_PRIVATE CPP_EXTERN const int
|
|
Java_org_videolan_Libbluray_methods_count =
|
|
sizeof(Java_org_videolan_Libbluray_methods)/sizeof(Java_org_videolan_Libbluray_methods[0]);
|
|
|