-
Notifications
You must be signed in to change notification settings - Fork 231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Background playback improvements #104
Changes from 8 commits
2b292a5
1e5af7d
7e15fe8
c314128
3342005
92ebe79
d3be75b
e59b7ce
dd9374d
af03faf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package `is`.xyz.mpv | ||
|
||
import android.content.BroadcastReceiver | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.util.Log | ||
|
||
class NotificationButtonReceiver : BroadcastReceiver() { | ||
override fun onReceive(context: Context?, intent: Intent?) { | ||
Log.v(TAG, "NotificationButtonReceiver: ${intent!!.action}") | ||
when(intent!!.action) { | ||
"$PREFIX.ACTION_PREV" -> MPVLib.command(arrayOf("playlist-prev")) | ||
"$PREFIX.ACTION_NEXT" -> MPVLib.command(arrayOf("playlist-next")) | ||
} | ||
} | ||
|
||
companion object { | ||
private val TAG = "mpv" | ||
private val PREFIX = "is.xyz.mpv" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <stdlib.h> | ||
#include <vector> | ||
#include <string> | ||
|
||
#include <jni.h> | ||
#include <android/bitmap.h> | ||
#include <mpv/client.h> | ||
|
||
extern "C" { | ||
#include <libswscale/swscale.h> | ||
}; | ||
|
||
#include "jni_utils.h" | ||
#include "globals.h" | ||
#include "log.h" | ||
|
||
extern "C" { | ||
jni_func(jobject, grabThumbnail, jint dimension); | ||
}; | ||
|
||
jni_func(jobject, grabThumbnail, jint dimension) { | ||
ALOGV("grabbing thumbnail\n"); | ||
|
||
mpv_node result; | ||
{ | ||
mpv_node c, c_arg0, c_arg1; | ||
mpv_node c_args[2]; | ||
mpv_node_list c_array; | ||
c_arg0.format = MPV_FORMAT_STRING; | ||
c_arg0.u.string = (char*) "screenshot-raw"; | ||
c_args[0] = c_arg0; | ||
c_arg1.format = MPV_FORMAT_STRING; | ||
c_arg1.u.string = (char*) "video"; | ||
c_args[1] = c_arg1; | ||
c_array.num = 2; | ||
c_array.values = c_args; | ||
c.format = MPV_FORMAT_NODE_ARRAY; | ||
c.u.list = &c_array; | ||
if (mpv_command_node(g_mpv, &c, &result) < 0) | ||
return NULL; | ||
} | ||
|
||
unsigned w, h; | ||
w = h = 0; | ||
struct mpv_byte_array *data = NULL; | ||
{ | ||
if (result.format != MPV_FORMAT_NODE_MAP) | ||
return NULL; | ||
for (int i = 0; i < result.u.list->num; i++) { | ||
std::string key(result.u.list->keys[i]); | ||
const mpv_node *val = &result.u.list->values[i]; | ||
if (key == "w" || key == "h") { | ||
if (val->format != MPV_FORMAT_INT64) | ||
return NULL; | ||
if (key == "w") | ||
w = val->u.int64; | ||
else | ||
h = val->u.int64; | ||
} else if (key == "format") { | ||
if (val->format != MPV_FORMAT_STRING) | ||
return NULL; | ||
if (strcmp(val->u.string, "bgr0")) | ||
return NULL; | ||
} else if (key == "data") { | ||
if (val->format != MPV_FORMAT_BYTE_ARRAY) | ||
return NULL; | ||
data = val->u.ba; | ||
} | ||
} | ||
} | ||
if (!w || !h || !data) | ||
return NULL; | ||
ALOGV("screenshot w:%u h:%u\n", w, h); | ||
|
||
// crop to square | ||
unsigned crop_left, crop_right, crop_top, crop_bottom; | ||
if (w > h) { | ||
crop_top = crop_bottom = 0; | ||
int tmp = w - h; | ||
crop_left = tmp / 2; | ||
crop_right = tmp / 2 + tmp % 2; | ||
} else { | ||
crop_left = crop_right = 0; | ||
int tmp = h - w; | ||
crop_top = tmp / 2; | ||
crop_bottom = tmp / 2 + tmp % 2; | ||
} | ||
unsigned new_w, new_h; | ||
new_w = w - crop_left - crop_right; | ||
new_h = h - crop_top - crop_bottom; | ||
ALOGV("cropped w:%u h:%u\n", new_w, new_h); | ||
|
||
std::vector<uint32_t> new_data; | ||
new_data.reserve(new_w * new_h); | ||
for (int y = 0; y < new_h; y++) { | ||
for (int x = 0; x < new_w; x++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can the inner loop be replaced with memcpy? |
||
int tx = x + crop_left, ty = y + crop_top; | ||
new_data[y*new_w + x] = ((uint32_t*) data->data)[ty*w + tx]; | ||
} | ||
} | ||
mpv_free_node_contents(&result); // frees data->data | ||
|
||
// convert & scale to appropriate size | ||
struct SwsContext *ctx = sws_getContext( | ||
new_w, new_h, AV_PIX_FMT_BGR0, | ||
dimension, dimension, AV_PIX_FMT_RGB32, | ||
SWS_BICUBIC, NULL, NULL, NULL); | ||
if (!ctx) | ||
return NULL; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're leaking new_data here. Probably better to replace with std::vector or similar so that RAII can be utilized. |
||
int src_stride = sizeof(uint32_t) * new_w, dst_stride = sizeof(uint32_t) * dimension; | ||
std::vector<uint8_t> scaled; | ||
scaled.reserve(dimension * dst_stride); | ||
uint8_t *src_p[] = { (uint8_t*) new_data.data() }, *dst_p[] = { scaled.data() }; | ||
sws_scale(ctx, src_p, &src_stride, 0, new_h, dst_p, &dst_stride); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All arrays you pass to |
||
sws_freeContext(ctx); | ||
|
||
|
||
// create android.graphics.Bitmap | ||
jintArray arr = env->NewIntArray(dimension * dimension); | ||
env->SetIntArrayRegion(arr, 0, dimension * dimension, (jint*) scaled.data()); | ||
|
||
jobject bitmap_config = | ||
env->GetStaticObjectField(android_graphics_Bitmap_Config, android_graphics_Bitmap_Config_ARGB_8888); | ||
jobject bitmap = | ||
env->CallStaticObjectMethod(android_graphics_Bitmap, android_graphics_Bitmap_createBitmap, | ||
arr, dimension, dimension, bitmap_config); | ||
env->DeleteLocalRef(arr); | ||
env->DeleteLocalRef(bitmap_config); | ||
|
||
return bitmap; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<vector android:height="24dp" android:viewportHeight="64.0" | ||
android:viewportWidth="64.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<!-- imported from <mpv>/etc/mpv-symbolic.svg --> | ||
<path android:fillAlpha="1" android:fillColor="#000000" | ||
android:fillType="nonZero" | ||
android:pathData="M32.58,2.91A27.95,27.95 0,0 0,4.63 30.86A27.95,27.95 0,0 0,32.58 58.81A27.95,27.95 0,0 0,60.53 30.86A27.95,27.95 0,0 0,32.58 2.91zM33.31,4.05A25.95,25.95 0,0 1,59.26 30.01A25.95,25.95 0,0 1,33.31 55.96A25.95,25.95 0,0 1,7.36 30.01A25.95,25.95 0,0 1,33.31 4.05z" | ||
android:strokeAlpha="0.99215686" android:strokeColor="#00000000" | ||
android:strokeLineCap="round" android:strokeLineJoin="bevel" android:strokeWidth="0.10161044"/> | ||
<path android:fillAlpha="1" android:fillColor="#000000" | ||
android:fillType="evenOdd" | ||
android:pathData="m32.21,18.13a12.85,12.85 0,0 0,-12.85 12.85,12.85 12.85,0 0,0 12.85,12.85 12.85,12.85 0,0 0,12.85 -12.85,12.85 12.85,0 0,0 -12.85,-12.85zM28.96,25.21 L38.17,30.79 28.96,36.66 28.96,25.21zM54.81,28.29a20,20 0,0 1,-20 20,20 20,0 0,1 -20,-20 20,20 0,0 1,20 -20,20 20,0 0,1 20,20z" | ||
android:strokeAlpha="1" android:strokeColor="#00000000" | ||
android:strokeLineCap="butt" android:strokeLineJoin="miter" android:strokeWidth="0.1"/> | ||
</vector> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<vector android:height="32dp" android:viewportHeight="24.0" | ||
android:viewportWidth="24.0" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<path android:fillColor="#FF000000" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/> | ||
</vector> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<vector android:height="32dp" android:viewportHeight="24.0" | ||
android:viewportWidth="24.0" android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<path android:fillColor="#FF000000" android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/> | ||
</vector> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't use "new" vector members after you call
reserve
, you need to doresize
, or just pass the size as argument to the constructor.