Skip to content

Commit

Permalink
Fix JNIEnv problems and attempt to decrease A/V artefacts
Browse files Browse the repository at this point in the history
  • Loading branch information
tretdm committed Apr 21, 2024
1 parent f08d604 commit 752ce78
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public class OvkMediaPlayer extends MediaPlayer {
private OnCompletionListener onCompletionListener;
private Handler handler;
private AudioTrack audio_track;
private byte[] videoBuffer;

// C++ player native functions
private native void naInit();
Expand Down Expand Up @@ -319,6 +320,7 @@ private void renderAudio(final byte[] buffer, final int length) {
audio_track.play();
prepared_audio_buffer = true;
}

try {
audio_track.write(buffer, 0, length);
} catch (Exception ignored) {
Expand All @@ -330,67 +332,69 @@ private void completePlayback() {
}

private void renderVideo(final byte[] buffer, final int length) {
new Thread(new Runnable() {
@Override
public void run() {
Canvas c;
OvkVideoTrack track = null;
for (int tracks_index = 0; tracks_index < tracks.size(); tracks_index++) {
if (tracks.get(tracks_index) instanceof OvkVideoTrack) {
track = (OvkVideoTrack) tracks.get(tracks_index);
}
}
if (track != null) {
int frame_width = track.frame_size[0];
int frame_height = track.frame_size[1];
if (frame_width > 0 && frame_height > 0) {
minVideoBufferSize = frame_width * frame_height * 4;
try {
// RGB_565 == 65K colours (16 bit)
// RGB_8888 == 16.7M colours (24 bit w/ alpha ch.)
int bpp = Build.VERSION.SDK_INT > 9 ? 16 : 24;
Bitmap.Config bmp_config =
bpp == 24 ? Bitmap.Config.RGB_565 : Bitmap.Config.ARGB_8888;
if(buffer != null && holder != null) {
holder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
if((c = holder.lockCanvas()) == null) {
Log.d(MPLAY_TAG, "Lock canvas failed");
return;
}
ByteBuffer bbuf =
ByteBuffer.allocateDirect(minVideoBufferSize);
bbuf.rewind();
for(int i = 0; i < buffer.length; i++) {
bbuf.put(i, buffer[i]);
}
bbuf.rewind();
Bitmap bmp = Bitmap.createBitmap(frame_width, frame_height, bmp_config);
bmp.copyPixelsFromBuffer(bbuf);
float aspect_ratio = (float) frame_width / (float) frame_height;
int scaled_width = (int)(aspect_ratio * (c.getHeight()));
c.drawBitmap(bmp,
null,
new RectF(
((c.getWidth() - scaled_width) / 2), 0,
((c.getWidth() - scaled_width) / 2) + scaled_width,
c.getHeight()),
null);
holder.unlockCanvasAndPost(c);
bmp.recycle();
bbuf.clear();
} else {
Log.d(MPLAY_TAG, "Video frame buffer is null");
}
} catch (Exception ex) {
ex.printStackTrace();
} catch (OutOfMemoryError oom) {
oom.printStackTrace();
stop();
Canvas c;
videoBuffer = buffer;
OvkVideoTrack track = null;
for (int tracks_index = 0; tracks_index < tracks.size(); tracks_index++) {
if (tracks.get(tracks_index) instanceof OvkVideoTrack) {
track = (OvkVideoTrack) tracks.get(tracks_index);
}
}
if (track != null) {
int frame_width = track.frame_size[0];
int frame_height = track.frame_size[1];
if (frame_width > 0 && frame_height > 0) {
minVideoBufferSize = frame_width * frame_height * 4;
try {
// RGB_565 == 65K colours (16 bit)
// RGB_8888 == 16.7M colours (24 bit w/ alpha ch.)
int bpp = Build.VERSION.SDK_INT > 9 ? 16 : 24;
Bitmap.Config bmp_config =
bpp == 24 ? Bitmap.Config.RGB_565 : Bitmap.Config.ARGB_8888;
if(videoBuffer != null && holder != null) {
holder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
if((c = holder.lockCanvas()) == null) {
Log.d(MPLAY_TAG, "Lock canvas failed");
return;
}
ByteBuffer bbuf =
ByteBuffer.allocateDirect(minVideoBufferSize);
bbuf.rewind();
for(int i = 0; i < videoBuffer.length; i++) {
bbuf.put(i, videoBuffer[i]);
}
bbuf.rewind();
Bitmap bmp = Bitmap.createBitmap(frame_width, frame_height, bmp_config);
bmp.copyPixelsFromBuffer(bbuf);
float aspect_ratio = (float) frame_width / (float) frame_height;
int scaled_width = (int)(aspect_ratio * (c.getHeight()));
videoBuffer = null;
c.drawBitmap(bmp,
null,
new RectF(
((c.getWidth() - scaled_width) / 2), 0,
((c.getWidth() - scaled_width) / 2) + scaled_width,
c.getHeight()),
null);
holder.unlockCanvasAndPost(c);
bmp.recycle();
bbuf.clear();
} else {
Log.d(MPLAY_TAG, "Video frame buffer is null");
}
} catch (Exception ex) {
ex.printStackTrace();
} catch (OutOfMemoryError oom) {
oom.printStackTrace();
stop();
}
try {
Thread.sleep((long) (1000 / track.frame_rate));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}

@Override
Expand Down
4 changes: 1 addition & 3 deletions ndk-modules/ovkmplayer/decoders/audiodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,7 @@ void *AudioDecoder::decodeInThread() {
}

bool AudioDecoder::start() {
pthread_t decoderThread;
pthread_create(&decoderThread, NULL, s_decodeInThread, (void*)this);
pthread_join(decoderThread, NULL);
decodeInThread();
return true;
}

Expand Down
1 change: 1 addition & 0 deletions ndk-modules/ovkmplayer/decoders/audiodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <../utils/pktqueue.h>
#include <../interfaces/ffwrap.h>
#include <android/log.h>
#include <android.h>

#define LOG_TAG "FFwrap"
#define LOG_LEVEL 10
Expand Down
75 changes: 69 additions & 6 deletions ndk-modules/ovkmplayer/decoders/videodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,95 @@ VideoDecoder::VideoDecoder(AVFormatContext *pFormatCtx,
}

bool VideoDecoder::prepare() {
gFrame = avcodec_alloc_frame();
return gFrame != NULL;
return true;
}

static void *s_decodeInThread(void *arg) {
return ((VideoDecoder*) arg)->decodeInThread();
}

void *VideoDecoder::decodeInThread() {
int status, dataSize, len;
AVPacket avPkt;
AVPacket avPkt;
int vWidth = gCodecCtx->width,
vHeight = gCodecCtx->height,
status, len,
dataSize = avpicture_get_size(AV_PIX_FMT_RGB32, vWidth, vHeight),
packetSize, tVideoFrames;
struct SwsContext *img_convert_ctx = NULL;

gBuffer = (short*) av_mallocz((size_t)dataSize);

while(av_read_frame(gFormatCtx, &avPkt)>=0) {
gFrame = avcodec_alloc_frame();
// It is from the video stream?
if(avPkt.stream_index == gStreamIndex) {
packetSize = avPkt.size;
struct SwsContext *img_convert_ctx = NULL;
avpicture_fill((AVPicture*) gFrame,
(const uint8_t*) gBuffer,
gCodecCtx->pix_fmt,
gCodecCtx->width,
gCodecCtx->height
);

avcodec_decode_video2(gCodecCtx, gFrame, &status, &avPkt);
if(!status || gFrame == NULL || packetSize == 0) {
tVideoFrames++;
continue;
}
AVPixelFormat pxf;

// TODO: Implement video decoding stages
//gInterface->onStreamDecoding((uint8_t*)gBuffer, dataSize / 2, gStreamIndex);
pxf = AV_PIX_FMT_BGR32;

convertYuv2Rgb(pxf, gFrame, dataSize);
tVideoFrames++;
gInterface->onStreamDecoding((uint8_t*)gBuffer, dataSize, gStreamIndex);
}
av_free(gFrame);
// Free the packet that was allocated by av_read_frame
av_free_packet(&avPkt);
}

av_free(gBuffer);

stop();
}

bool VideoDecoder::start() {
decodeInThread();
return true;
}

short* VideoDecoder::convertYuv2Rgb(AVPixelFormat pxf, AVFrame* frame, int length) {
AVFrame *frameRGB = av_frame_alloc();
AVPixelFormat output_pxf = pxf;

avpicture_fill((AVPicture *)frameRGB, (uint8_t*)gBuffer, output_pxf,
gCodecCtx->width, gCodecCtx->height);
const int width = gCodecCtx->width, height = gCodecCtx->height;
SwsContext* img_convert_ctx = sws_getContext(width, height,
gCodecCtx->pix_fmt,
width, height, output_pxf, SWS_BICUBIC,
NULL, NULL, NULL);


if(img_convert_ctx == NULL) {
LOGE(10, "Cannot initialize the conversion context!");
sws_freeContext(img_convert_ctx);
return NULL;
}

int ret = sws_scale(img_convert_ctx, (const uint8_t* const*)frame->data, frame->linesize, 0,
gCodecCtx->height, frameRGB->data, frameRGB->linesize);
if(frameRGB->data[0] == NULL) {
LOGE(10, "SWS_Scale failed");
}
av_free(frameRGB);
av_frame_unref(frameRGB);
sws_freeContext(img_convert_ctx);
return gBuffer;
}

bool VideoDecoder::stop() {
av_free(gFrame);
avcodec_close(gCodecCtx);
Expand Down
9 changes: 6 additions & 3 deletions ndk-modules/ovkmplayer/decoders/videodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <../utils/pktqueue.h>

#include <android/log.h>

#define LOG_TAG "FFwrap"
#define LOG_LEVEL 10
#define LOGD(level, ...) if (level <= LOG_LEVEL) {__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__);}
Expand Down Expand Up @@ -70,9 +72,10 @@ class VideoDecoder {
AVStream *gStream;
IFFmpegWrapper *gInterface;
AVFrame *gFrame;
bool start();
bool stop();
void* decodeInThread();
bool start();
bool stop();
void* decodeInThread();
short* convertYuv2Rgb(AVPixelFormat pxf, AVFrame* frame, int length);
private:
PacketQueue* gPktQueue;
};
Expand Down
7 changes: 6 additions & 1 deletion ndk-modules/ovkmplayer/interfaces/ffwrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <stdint.h>

#include <jni.h>

class IFFmpegWrapper {
public:
IFFmpegWrapper() {};
Expand All @@ -15,8 +17,11 @@ class IFFmpegWrapper {
int bufferLen,
int streamIndex) = 0;
virtual void onChangePlaybackState(int playbackState) = 0;
virtual void onChangeWrapperState(int wrapperState) = 0;
JNIEnv *env;
jobject instance;
private:
bool gDebugMode;
};

#endif
#endif
Loading

0 comments on commit 752ce78

Please sign in to comment.