Skip to content

Commit e95e721

Browse files
committed
add autoscale option into player
1 parent 198b719 commit e95e721

File tree

12 files changed

+179
-104
lines changed

12 files changed

+179
-104
lines changed

AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
</activity>
2626

2727
</application>
28-
<uses-sdk android:minSdkVersion="3" />
28+
<uses-sdk android:minSdkVersion="4" />
2929
<uses-permission android:name="android.permission.WAKE_LOCK"/>
3030
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3131
</manifest>

default.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
# project structure.
99

1010
# Project target.
11-
target=android-3
11+
target=android-4
1212
# Indicates whether an apk should be generated for each density.
1313
split.density=false

jni/include/android/surface.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/*
2+
* Copyright (C) 2011 Petr Havlena [email protected]
23
* Copyright (C) 2009 The Android Open Source Project
34
*
45
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,13 +21,13 @@
2021
#include <stdint.h>
2122
#include <jni.h>
2223

23-
#define ANDROID_SURFACE_RESULT_SUCCESS 0
24-
#define ANDROID_SURFACE_RESULT_NOT_VALID -1
25-
#define ANDROID_SURFACE_RESULT_COULDNT_LOCK -2
26-
#define ANDROID_SURFACE_RESULT_COULDNT_UNLOCK_AND_POST -3
27-
#define ANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_SURFACE -4
28-
#define ANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_CLIENT -5
29-
#define ANDROID_SURFACE_RESULT_JNI_EXCEPTION -6
24+
#define ANDROID_SURFACE_RESULT_SUCCESS 0
25+
#define ANDROID_SURFACE_RESULT_NOT_VALID -1
26+
#define ANDROID_SURFACE_RESULT_COULDNT_LOCK -2
27+
#define ANDROID_SURFACE_RESULT_COULDNT_UNLOCK_AND_POST -3
28+
#define ANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_SURFACE -4
29+
#define ANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_CLIENT -5
30+
#define ANDROID_SURFACE_RESULT_JNI_EXCEPTION -6
3031

3132
#ifdef __cplusplus
3233
extern "C" {
@@ -36,7 +37,7 @@ int AndroidSurface_register(JNIEnv* env, jobject jsurface);
3637

3738
int AndroidSurface_getPixels(int width, int height, void** pixels);
3839

39-
int AndroidSurface_updateSurface();
40+
int AndroidSurface_updateSurface(bool autoscale = true);
4041

4142
int AndroidSurface_unregister();
4243

jni/jni/com_media_ffmpeg_FFMpegPlayer.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,28 @@ com_media_ffmpeg_FFMpegPlayer_pause(JNIEnv *env, jobject thiz)
220220
process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
221221
}
222222

223+
static void
224+
com_media_ffmpeg_FFMpegPlayer_setResolution(JNIEnv *env, jobject thiz, jint width, jint height)
225+
{
226+
MediaPlayer* mp = getMediaPlayer(env, thiz);
227+
if (mp == NULL ) {
228+
jniThrowException(env, "java/lang/IllegalStateException", NULL);
229+
return;
230+
}
231+
process_media_player_call( env, thiz, mp->setResolution(width, height), NULL, NULL );
232+
}
233+
234+
static void
235+
com_media_ffmpeg_FFMpegPlayer_setAutoscale(JNIEnv *env, jobject thiz, jboolean value)
236+
{
237+
MediaPlayer* mp = getMediaPlayer(env, thiz);
238+
if (mp == NULL ) {
239+
jniThrowException(env, "java/lang/IllegalStateException", NULL);
240+
return;
241+
}
242+
process_media_player_call( env, thiz, mp->setAutoscale(value), NULL, NULL );
243+
}
244+
223245
static jboolean
224246
com_media_ffmpeg_FFMpegPlayer_isPlaying(JNIEnv *env, jobject thiz)
225247
{
@@ -406,6 +428,8 @@ static JNINativeMethod gMethods[] = {
406428
{"prepare", "()V", (void *)com_media_ffmpeg_FFMpegPlayer_prepare},
407429
{"_start", "()V", (void *)com_media_ffmpeg_FFMpegPlayer_start},
408430
{"_stop", "()V", (void *)com_media_ffmpeg_FFMpegPlayer_stop},
431+
{"_setResolution", "(II)V", (void *)com_media_ffmpeg_FFMpegPlayer_setResolution},
432+
{"_setAutoscale", "(Z)V", (void *)com_media_ffmpeg_FFMpegPlayer_setAutoscale},
409433
{"getVideoWidth", "()I", (void *)com_media_ffmpeg_FFMpegPlayer_getVideoWidth},
410434
{"getVideoHeight", "()I", (void *)com_media_ffmpeg_FFMpegPlayer_getVideoHeight},
411435
{"seekTo", "(I)V", (void *)com_media_ffmpeg_FFMpegPlayer_seekTo},

jni/libmediaplayer/mediaplayer.cpp

Lines changed: 66 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ extern "C" {
2525
#include "mediaplayer.h"
2626
#include "output.h"
2727

28-
#define FPS_DEBUGGING false
29-
3028
#define LOG_TAG "FFMpegMediaPlayer"
3129

3230
static MediaPlayer* sPlayer;
@@ -39,34 +37,16 @@ class VideoCallback : public DecoderVideoCallback
3937

4038
void VideoCallback::onDecode(AVFrame* frame, double pts)
4139
{
42-
if(FPS_DEBUGGING)
43-
{
44-
timeval pTime;
45-
static int frames = 0;
46-
static double t1 = -1;
47-
static double t2 = -1;
48-
49-
gettimeofday(&pTime, NULL);
50-
t2 = pTime.tv_sec + (pTime.tv_usec / 1000000.0);
51-
if (t1 == -1 || t2 > t1 + 1) {
52-
LOGI("Video fps:%i", frames);
53-
//sPlayer->notify(MEDIA_INFO_FRAMERATE_VIDEO, frames, -1);
54-
t1 = t2;
55-
frames = 0;
56-
}
57-
frames++;
58-
}
59-
6040
// Convert the image from its native format to RGB
6141
sws_scale(sPlayer->mConvertCtx,
6242
frame->data,
6343
frame->linesize,
64-
0,
44+
0,
6545
sPlayer->mVideoHeight,
6646
sPlayer->mFrame->data,
67-
sPlayer->mFrame->linesize);
47+
sPlayer->mFrame->linesize);
6848

69-
Output::VideoDriver_updateSurface();
49+
Output::VideoDriver_updateSurface(sPlayer->mAutoscale);
7050
}
7151

7252
class AudioCallback : public DecoderAudioCallback
@@ -77,24 +57,6 @@ class AudioCallback : public DecoderAudioCallback
7757

7858
void AudioCallback::onDecode(int16_t* buffer, int buffer_size)
7959
{
80-
if(FPS_DEBUGGING)
81-
{
82-
timeval pTime;
83-
static int frames = 0;
84-
static double t1 = -1;
85-
static double t2 = -1;
86-
87-
gettimeofday(&pTime, NULL);
88-
t2 = pTime.tv_sec + (pTime.tv_usec / 1000000.0);
89-
if (t1 == -1 || t2 > t1 + 1) {
90-
LOGI("Video fps:%i", frames);
91-
//sPlayer->notify(MEDIA_INFO_FRAMERATE_VIDEO, frames, -1);
92-
t1 = t2;
93-
frames = 0;
94-
}
95-
frames++;
96-
}
97-
9860
if(Output::AudioDriver_write(buffer, buffer_size) <= 0) {
9961
LOGE("Couldn't write samples to audio track");
10062
}
@@ -152,8 +114,14 @@ void DecodeLoop::run()
152114
usleep(200);
153115
continue;
154116
}
117+
118+
if(mPaused) {
119+
usleep(200);
120+
continue;
121+
}
155122

156-
123+
sPlayer->mLock.lock();
124+
157125
if(av_read_frame(mContext, &pPacket) < 0) {
158126
mEnding = true;
159127
continue;
@@ -170,6 +138,8 @@ void DecodeLoop::run()
170138
// Free the packet that was allocated by av_read_frame
171139
av_free_packet(&pPacket);
172140
}
141+
142+
sPlayer->mLock.unlock();
173143
}
174144

175145
//waits on end of video thread
@@ -201,6 +171,7 @@ MediaPlayer::MediaPlayer()
201171
mPrepareSync = false;
202172
mPrepareStatus = NO_ERROR;
203173
mLoop = false;
174+
mAutoscale = true;
204175
mLeftVolume = mRightVolume = 1.0;
205176
mVideoWidth = mVideoHeight = 0;
206177
sPlayer = this;
@@ -290,11 +261,11 @@ status_t MediaPlayer::prepareVideo()
290261
mVideoHeight = codec_ctx->height;
291262
mDuration = mMovieFile->duration;
292263

293-
mConvertCtx = sws_getContext(stream->codec->width,
294-
stream->codec->height,
264+
mConvertCtx = sws_getContext(mVideoWidth,
265+
mVideoHeight,
295266
stream->codec->pix_fmt,
296-
stream->codec->width,
297-
stream->codec->height,
267+
mVideoWidth,
268+
mVideoHeight,
298269
PIX_FMT_RGB565,
299270
SWS_POINT,
300271
NULL,
@@ -305,27 +276,37 @@ status_t MediaPlayer::prepareVideo()
305276
return INVALID_OPERATION;
306277
}
307278

308-
void* pixels;
309-
if (Output::VideoDriver_getPixels(stream->codec->width,
310-
stream->codec->height,
311-
&pixels) != ANDROID_SURFACE_RESULT_SUCCESS) {
279+
if(!createVideoSurface(mVideoWidth, mVideoHeight)) {
312280
return INVALID_OPERATION;
313281
}
314282

315-
mFrame = avcodec_alloc_frame();
316-
if (mFrame == NULL) {
317-
return INVALID_OPERATION;
283+
return NO_ERROR;
284+
}
285+
286+
bool MediaPlayer::createVideoSurface(int width, int height)
287+
{
288+
void* pixels;
289+
if (Output::VideoDriver_getPixels(width, height, &pixels)
290+
!= ANDROID_SURFACE_RESULT_SUCCESS)
291+
{
292+
return false;
318293
}
319-
// Assign appropriate parts of buffer to image planes in pFrameRGB
320-
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
321-
// of AVPicture
322-
avpicture_fill((AVPicture *) mFrame,
323-
(uint8_t *) pixels,
324-
PIX_FMT_RGB565,
325-
stream->codec->width,
326-
stream->codec->height);
327294

328-
return NO_ERROR;
295+
mFrame = avcodec_alloc_frame();
296+
if (mFrame == NULL) {
297+
return false;
298+
}
299+
300+
// Assign appropriate parts of buffer to image planes in pFrameRGB
301+
// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
302+
// of AVPicture
303+
avpicture_fill((AVPicture *) mFrame,
304+
(uint8_t *) pixels,
305+
PIX_FMT_RGB565,
306+
width,
307+
height);
308+
309+
return true;
329310
}
330311

331312
status_t MediaPlayer::prepare()
@@ -448,15 +429,35 @@ status_t MediaPlayer::pause()
448429
{
449430
Mutex::AutoLock _l(&mLock);
450431

451-
mCurrentState = MEDIA_PLAYER_PAUSED;
432+
mDecodingLoop->pause();
433+
452434
return NO_ERROR;
453435
}
454436

455437
bool MediaPlayer::isPlaying()
456438
{
457439
Mutex::AutoLock _l(&mLock);
458-
return mCurrentState == MEDIA_PLAYER_STARTED ||
459-
mCurrentState == MEDIA_PLAYER_DECODED;
440+
return mDecodingLoop->isPlaying();
441+
}
442+
443+
status_t MediaPlayer::setAutoscale(bool value)
444+
{
445+
if (mCurrentState < MEDIA_PLAYER_PREPARED) {
446+
return INVALID_OPERATION;
447+
}
448+
449+
mAutoscale = value;
450+
451+
return NO_ERROR;
452+
}
453+
454+
status_t MediaPlayer::setResolution(int width, int height)
455+
{
456+
if (mCurrentState < MEDIA_PLAYER_PREPARED) {
457+
return INVALID_OPERATION;
458+
}
459+
460+
return NO_ERROR;
460461
}
461462

462463
status_t MediaPlayer::getVideoWidth(int *w)

jni/libmediaplayer/mediaplayer.h

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,17 @@ class DecodeLoop : public Thread
123123

124124
DecodeLoopCallback* mCallback;
125125
bool mEnding;
126+
bool mPaused;
126127

127128
public:
128129
DecodeLoop(AVFormatContext* context, int audioStreamId, int videoStreamId, DecodeLoopCallback* callback);
129130
~DecodeLoop();
130131

131132
virtual void run();
132133
void suspend();
134+
void resume() { mPaused = false; };
135+
void pause() { mPaused = true; };
136+
bool isPlaying() { return !mPaused; };
133137
};
134138

135139
// ----------------------------------------------------------------------------
@@ -145,6 +149,8 @@ class MediaPlayer : private DecodeLoopCallback
145149
public:
146150
MediaPlayer();
147151
~MediaPlayer();
152+
status_t setAutoscale(bool value);
153+
status_t setResolution(int width, int height);
148154
status_t setDataSource(const char *url);
149155
status_t setVideoSurface(JNIEnv* env, jobject jsurface);
150156
status_t setListener(MediaPlayerListener *listener);
@@ -171,45 +177,46 @@ class MediaPlayer : private DecodeLoopCallback
171177
status_t resume();
172178

173179
private:
180+
bool createVideoSurface(int width, int height);
174181
status_t prepareAudio();
175182
status_t prepareVideo();
176183
bool shouldCancel(PacketQueue* queue);
177184
static void ffmpegNotify(void* ptr, int level, const char* fmt, va_list vl);
178185

179-
double mTime;
186+
double mTime;
180187

181-
PacketQueue* mVideoQueue;
182188
Mutex mLock;
183-
//Mutex mNotifyLock;
184-
//Condition mSignal;
185189

186190
MediaPlayerListener* mListener;
187191
AVFormatContext* mMovieFile;
188192
int mAudioStreamIndex;
189193
int mVideoStreamIndex;
190194

191-
DecodeLoop* mDecodingLoop;
195+
DecodeLoop* mDecodingLoop;
192196

193-
void* mCookie;
194-
media_player_states mCurrentState;
195-
int mDuration;
196-
int mCurrentPosition;
197-
int mSeekPosition;
198-
bool mPrepareSync;
199-
status_t mPrepareStatus;
200-
int mStreamType;
201-
bool mLoop;
202-
float mLeftVolume;
203-
float mRightVolume;
197+
void* mCookie;
198+
media_player_states mCurrentState;
199+
int mDuration;
200+
int mCurrentPosition;
201+
int mSeekPosition;
202+
bool mPrepareSync;
203+
status_t mPrepareStatus;
204+
int mStreamType;
205+
bool mLoop;
206+
float mLeftVolume;
207+
float mRightVolume;
204208

205209
public:
206-
struct SwsContext* mConvertCtx;
207-
AVFrame* mFrame;
208-
int mVideoWidth;
209-
int mVideoHeight;
210+
bool mAutoscale;
211+
struct SwsContext* mConvertCtx;
212+
AVFrame* mFrame;
213+
int mVideoWidth;
214+
int mVideoHeight;
210215

211216
protected:
212217
virtual void onCompleted();
218+
219+
friend class DecodeLoop;
213220
};
214221

215222
#endif // FFMPEG_MEDIAPLAYER_H

0 commit comments

Comments
 (0)