提交 2303913b 编写于 作者: Z Zhang Rui

ios: add IJKSDLHudViewController

上级 e7368611
......@@ -719,7 +719,7 @@ static int drain_output_buffer_l(JNIEnv *env, IJKFF_Pipenode *node, int64_t time
}
}
} else if (output_buffer_index >= 0) {
ffp->vdps = SDL_SpeedSamplerAdd(&opaque->sampler, FFP_SHOW_VDPS_MEDIACODEC, "vdps[MediaCodec]");
ffp->stat.vdps = SDL_SpeedSamplerAdd(&opaque->sampler, FFP_SHOW_VDPS_MEDIACODEC, "vdps[MediaCodec]");
if (dequeue_count)
++*dequeue_count;
......
......@@ -50,8 +50,22 @@
#define FFP_PROP_FLOAT_VIDEO_DECODE_FRAMES_PER_SECOND 10001
#define FFP_PROP_FLOAT_VIDEO_OUTPUT_FRAMES_PER_SECOND 10002
#define FFP_PROP_FLOAT_PLAYBACK_RATE 10003
#define FFP_PROP_FLOAT_AVDELAY 10004
#define FFP_PROP_FLOAT_AVDIFF 10005
#define FFP_PROP_INT64_SELECTED_VIDEO_STREAM 20001
#define FFP_PROP_INT64_SELECTED_AUDIO_STREAM 20002
#define FFP_PROP_INT64_SELECTED_VIDEO_STREAM 20001
#define FFP_PROP_INT64_SELECTED_AUDIO_STREAM 20002
#define FFP_PROP_INT64_VIDEO_DECODER 20003
#define FFP_PROP_INT64_AUDIO_DECODER 20004
#define FFP_PROPV_DECODER_UNKNOWN 0
#define FFP_PROPV_DECODER_AVCODEC 1
#define FFP_PROPV_DECODER_MEDIACODEC 2
#define FFP_PROPV_DECODER_VIDEOTOOLBOX 3
#define FFP_PROP_INT64_VIDEO_CACHED_DURATION 20005
#define FFP_PROP_INT64_AUDIO_CACHED_DURATION 20006
#define FFP_PROP_INT64_VIDEO_CACHED_BYTES 20007
#define FFP_PROP_INT64_AUDIO_CACHED_BYTES 20008
#define FFP_PROP_INT64_VIDEO_CACHED_PACKETS 20009
#define FFP_PROP_INT64_AUDIO_CACHED_PACKETS 20010
#endif
......@@ -398,7 +398,7 @@ static int decoder_decode_frame(FFPlayer *ffp, Decoder *d, AVFrame *frame, AVSub
case AVMEDIA_TYPE_VIDEO: {
ret = avcodec_decode_video2(d->avctx, frame, &got_frame, &d->pkt_temp);
if (got_frame) {
ffp->vdps = SDL_SpeedSamplerAdd(&ffp->vdps_sampler, FFP_SHOW_VDPS_AVCODEC, "vdps[avcodec]");
ffp->stat.vdps = SDL_SpeedSamplerAdd(&ffp->vdps_sampler, FFP_SHOW_VDPS_AVCODEC, "vdps[avcodec]");
if (ffp->decoder_reorder_pts == -1) {
frame->pts = av_frame_get_best_effort_timestamp(frame);
} else if (ffp->decoder_reorder_pts) {
......@@ -651,7 +651,7 @@ static void video_image_display2(FFPlayer *ffp)
vp = frame_queue_peek(&is->pictq);
if (vp->bmp) {
SDL_VoutDisplayYUVOverlay(ffp->vout, vp->bmp);
ffp->vfps = SDL_SpeedSamplerAdd(&ffp->vfps_sampler, FFP_SHOW_VFPS_FFPLAY, "vfps[ffplay]");
ffp->stat.vfps = SDL_SpeedSamplerAdd(&ffp->vfps_sampler, FFP_SHOW_VFPS_FFPLAY, "vfps[ffplay]");
if (!ffp->first_video_frame_rendered) {
ffp->first_video_frame_rendered = 1;
ffp_notify_msg1(ffp, FFP_MSG_VIDEO_RENDERING_START);
......@@ -950,7 +950,7 @@ static void step_to_next_frame_l(FFPlayer *ffp)
is->step = 1;
}
static double compute_target_delay(double delay, VideoState *is)
static double compute_target_delay(FFPlayer *ffp, double delay, VideoState *is)
{
double sync_threshold, diff = 0;
......@@ -974,6 +974,10 @@ static double compute_target_delay(double delay, VideoState *is)
}
}
if (ffp) {
ffp->stat.avdelay = delay;
ffp->stat.avdiff = diff;
}
#ifdef FFP_SHOW_AUDIO_DELAY
av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n",
delay, -diff);
......@@ -1055,7 +1059,7 @@ retry:
if (redisplay)
delay = 0.0;
else
delay = compute_target_delay(last_duration, is);
delay = compute_target_delay(ffp, last_duration, is);
time= av_gettime_relative()/1000000.0;
if (isnan(is->frame_timer) || time < is->frame_timer)
......@@ -3691,6 +3695,11 @@ void ffp_check_buffering_l(FFPlayer *ffp)
int64_t audio_cached_duration = -1;
int64_t video_cached_duration = -1;
ffp->stat.video_cached_bytes = is->videoq.size;
ffp->stat.audio_cached_bytes = is->audioq.size;
ffp->stat.video_cached_packets = is->videoq.nb_packets;
ffp->stat.audio_cached_packets = is->audioq.nb_packets;
if (is->audio_st && audio_time_base_valid) {
audio_cached_duration = is->audioq.duration * av_q2d(is->audio_st->time_base) * 1000;
#ifdef FFP_SHOW_DEMUX_CACHE
......@@ -3715,6 +3724,8 @@ void ffp_check_buffering_l(FFPlayer *ffp)
is->audioq_duration = audio_cached_duration;
is->videoq_duration = video_cached_duration;
ffp->stat.audio_cached_duration = audio_cached_duration;
ffp->stat.video_cached_duration = video_cached_duration;
if (video_cached_duration > 0 && audio_cached_duration > 0) {
cached_duration_in_ms = (int)IJKMIN(video_cached_duration, audio_cached_duration);
......@@ -3905,11 +3916,15 @@ float ffp_get_property_float(FFPlayer *ffp, int id, float default_value)
{
switch (id) {
case FFP_PROP_FLOAT_VIDEO_DECODE_FRAMES_PER_SECOND:
return ffp ? ffp->vdps : default_value;
return ffp ? ffp->stat.vdps : default_value;
case FFP_PROP_FLOAT_VIDEO_OUTPUT_FRAMES_PER_SECOND:
return ffp ? ffp->vfps : default_value;
return ffp ? ffp->stat.vfps : default_value;
case FFP_PROP_FLOAT_PLAYBACK_RATE:
return ffp ? ffp->pf_playback_rate : default_value;
case FFP_PROP_FLOAT_AVDELAY:
return ffp ? ffp->stat.avdelay : default_value;
case FFP_PROP_FLOAT_AVDIFF:
return ffp ? ffp->stat.avdiff : default_value;
default:
return default_value;
}
......@@ -3936,6 +3951,37 @@ int64_t ffp_get_property_int64(FFPlayer *ffp, int id, int64_t default_value)
if (!ffp || !ffp->is)
return default_value;
return ffp->is->audio_stream;
case FFP_PROP_INT64_VIDEO_DECODER:
if (!ffp)
return default_value;
return ffp->stat.vdec_type;
case FFP_PROP_INT64_AUDIO_DECODER:
return FFP_PROPV_DECODER_AVCODEC;
case FFP_PROP_INT64_VIDEO_CACHED_DURATION:
if (!ffp)
return default_value;
return ffp->stat.video_cached_duration;
case FFP_PROP_INT64_AUDIO_CACHED_DURATION:
if (!ffp)
return default_value;
return ffp->stat.audio_cached_duration;
case FFP_PROP_INT64_VIDEO_CACHED_BYTES:
if (!ffp)
return default_value;
return ffp->stat.video_cached_bytes;
case FFP_PROP_INT64_AUDIO_CACHED_BYTES:
if (!ffp)
return default_value;
return ffp->stat.audio_cached_bytes;
case FFP_PROP_INT64_VIDEO_CACHED_PACKETS:
if (!ffp)
return default_value;
return ffp->stat.video_cached_packets;
case FFP_PROP_INT64_AUDIO_CACHED_PACKETS:
if (!ffp)
return default_value;
return ffp->stat.audio_cached_packets;
default:
return default_value;
}
......
......@@ -444,6 +444,22 @@ static SDL_Surface *screen;
* end at line 330 in ffplay.c
* near packet_queue_put
****************************************************************************/
typedef struct FFStatistic
{
int64_t vdec_type;
float vfps;
float vdps;
float avdelay;
float avdiff;
int64_t video_cached_duration;
int64_t audio_cached_duration;
int64_t video_cached_bytes;
int64_t audio_cached_bytes;
int64_t video_cached_packets;
int64_t audio_cached_packets;
} FFStatistic;
/* ffplayer */
struct IjkMediaMeta;
......@@ -587,15 +603,14 @@ typedef struct FFPlayer {
SDL_SpeedSampler vfps_sampler;
SDL_SpeedSampler vdps_sampler;
float vfps;
float vdps;
/* filters */
SDL_mutex *vf_mutex;
SDL_mutex *af_mutex;
int vf_changed;
int af_changed;
float pf_playback_rate;
FFStatistic stat;
} FFPlayer;
#define fftime_to_milliseconds(ts) (av_rescale(ts, 1000, AV_TIME_BASE));
......@@ -704,15 +719,14 @@ inline static void ffp_reset_internal(FFPlayer *ffp)
SDL_SpeedSamplerReset(&ffp->vfps_sampler);
SDL_SpeedSamplerReset(&ffp->vdps_sampler);
ffp->vfps = 0.0f;
ffp->vdps = 0.0f;
/* filters */
ffp->vf_changed = 0;
ffp->af_changed = 0;
ffp->pf_playback_rate = 1.0f;
msg_queue_flush(&ffp->msg_queue);
memset(&ffp->stat, 0, sizeof(ffp->stat));
}
inline static void ffp_notify_msg1(FFPlayer *ffp, int what) {
......
......@@ -70,6 +70,12 @@
E654EAEA1B6B295200B0F2D0 /* IJKFFMoviePlayerController.h in Headers */ = {isa = PBXBuildFile; fileRef = E66F8DE517EFD9C300354D80 /* IJKFFMoviePlayerController.h */; settings = {ATTRIBUTES = (Public, ); }; };
E654EAEC1B6B295200B0F2D0 /* IJKFFOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = E62139BC180FA89A00553533 /* IJKFFOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
E654EAED1B6B29C100B0F2D0 /* IJKMediaPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = E66F8DC217EECB1E00354D80 /* IJKMediaPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
E68B7AC51C1E7F20001DE241 /* IJKSDLHudViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = E68B7AC31C1E7F20001DE241 /* IJKSDLHudViewController.h */; };
E68B7AC61C1E7F20001DE241 /* IJKSDLHudViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E68B7AC41C1E7F20001DE241 /* IJKSDLHudViewController.m */; };
E68B7ACF1C1E97B0001DE241 /* IJKSDLHudViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E68B7ACD1C1E97B0001DE241 /* IJKSDLHudViewCell.h */; };
E68B7AD01C1E97B0001DE241 /* IJKSDLHudViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E68B7ACE1C1E97B0001DE241 /* IJKSDLHudViewCell.m */; };
E68B7ADA1C1FCA45001DE241 /* NSString+IJKMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = E68B7AD81C1FCA45001DE241 /* NSString+IJKMedia.h */; };
E68B7ADB1C1FCA45001DE241 /* NSString+IJKMedia.m in Sources */ = {isa = PBXBuildFile; fileRef = E68B7AD91C1FCA45001DE241 /* NSString+IJKMedia.m */; };
E69BE5511B93FED300AFBA3F /* allformats.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE54A1B93FED300AFBA3F /* allformats.c */; };
E69BE5531B93FED300AFBA3F /* async.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE54B1B93FED300AFBA3F /* async.c */; };
E69BE5561B93FED300AFBA3F /* ijkinject.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE54D1B93FED300AFBA3F /* ijkinject.c */; };
......@@ -153,6 +159,12 @@
E67C4E0619D15EEA00415CEE /* IJKAVMoviePlayerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IJKAVMoviePlayerController.h; path = IJKMediaPlayer/IJKAVMoviePlayerController.h; sourceTree = "<group>"; };
E67C4E0719D15EEA00415CEE /* IJKAVMoviePlayerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IJKAVMoviePlayerController.m; path = IJKMediaPlayer/IJKAVMoviePlayerController.m; sourceTree = "<group>"; };
E67FB4AC1B4A766F00AA94AA /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
E68B7AC31C1E7F20001DE241 /* IJKSDLHudViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJKSDLHudViewController.h; sourceTree = "<group>"; };
E68B7AC41C1E7F20001DE241 /* IJKSDLHudViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJKSDLHudViewController.m; sourceTree = "<group>"; };
E68B7ACD1C1E97B0001DE241 /* IJKSDLHudViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJKSDLHudViewCell.h; sourceTree = "<group>"; };
E68B7ACE1C1E97B0001DE241 /* IJKSDLHudViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJKSDLHudViewCell.m; sourceTree = "<group>"; };
E68B7AD81C1FCA45001DE241 /* NSString+IJKMedia.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+IJKMedia.h"; sourceTree = "<group>"; };
E68B7AD91C1FCA45001DE241 /* NSString+IJKMedia.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+IJKMedia.m"; sourceTree = "<group>"; };
E69007F11B96E2A600EB346D /* url.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = url.h; sourceTree = "<group>"; };
E6903EC017EAF6C500CFD954 /* IJKMediaPlayer-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IJKMediaPlayer-Prefix.pch"; sourceTree = "<group>"; };
E6903EC117EAF6C500CFD954 /* IJKMediaPlayback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IJKMediaPlayback.h; path = IJKMediaPlayer/IJKMediaPlayback.h; sourceTree = "<group>"; };
......@@ -600,6 +612,10 @@
E6EE92B51878230C009EAB56 /* IJKSDLGLShader.m */,
E6EE92B61878230C009EAB56 /* IJKSDLGLView.h */,
E6EE92B71878230C009EAB56 /* IJKSDLGLView.m */,
E68B7AC31C1E7F20001DE241 /* IJKSDLHudViewController.h */,
E68B7AC41C1E7F20001DE241 /* IJKSDLHudViewController.m */,
E68B7ACD1C1E97B0001DE241 /* IJKSDLHudViewCell.h */,
E68B7ACE1C1E97B0001DE241 /* IJKSDLHudViewCell.m */,
);
name = ios;
path = ../../ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijksdl/ios;
......@@ -621,6 +637,8 @@
E6716E4A1807E5FC00B3FBC1 /* IJKMediaUtils.m */,
E65DC3B719D93D5F004F8A08 /* IJKKVOController.h */,
E65DC3B819D93D5F004F8A08 /* IJKKVOController.m */,
E68B7AD81C1FCA45001DE241 /* NSString+IJKMedia.h */,
E68B7AD91C1FCA45001DE241 /* NSString+IJKMedia.m */,
);
name = IJKMediaPlayer;
sourceTree = "<group>";
......@@ -632,6 +650,8 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
E68B7AC51C1E7F20001DE241 /* IJKSDLHudViewController.h in Headers */,
E68B7ADA1C1FCA45001DE241 /* NSString+IJKMedia.h in Headers */,
E654EAE81B6B295200B0F2D0 /* IJKAVMoviePlayerController.h in Headers */,
E654EAEA1B6B295200B0F2D0 /* IJKFFMoviePlayerController.h in Headers */,
E654EAEC1B6B295200B0F2D0 /* IJKFFOptions.h in Headers */,
......@@ -642,6 +662,7 @@
E69BE5591B9405BD00AFBA3F /* ijkavformat.h in Headers */,
E654EAED1B6B29C100B0F2D0 /* IJKMediaPlayer.h in Headers */,
E654EAE91B6B295200B0F2D0 /* IJKMPMoviePlayerController.h in Headers */,
E68B7ACF1C1E97B0001DE241 /* IJKSDLHudViewCell.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -761,6 +782,7 @@
E607FFE11B7B62E3005F11A6 /* IJKDeviceModel.m in Sources */,
E654EAA31B6B283700B0F2D0 /* IJKAudioKit.m in Sources */,
E654EAAA1B6B284300B0F2D0 /* IJKMPMoviePlayerController.m in Sources */,
E68B7AD01C1E97B0001DE241 /* IJKSDLHudViewCell.m in Sources */,
E654EACB1B6B288A00B0F2D0 /* ijksdl_vout_overlay_videotoolbox.m in Sources */,
E654EAB11B6B285900B0F2D0 /* ff_ffpipenode.c in Sources */,
E654EAC41B6B287E00B0F2D0 /* ijksdl_stdinc.c in Sources */,
......@@ -775,6 +797,7 @@
E654EAC31B6B287E00B0F2D0 /* ijksdl_mutex.c in Sources */,
E654EACD1B6B288A00B0F2D0 /* IJKSDLAudioQueueController.m in Sources */,
E654EAC51B6B287E00B0F2D0 /* ijksdl_thread.c in Sources */,
E68B7ADB1C1FCA45001DE241 /* NSString+IJKMedia.m in Sources */,
E654EAB21B6B285900B0F2D0 /* ff_ffplay.c in Sources */,
E654EAC01B6B287E00B0F2D0 /* ijksdl_aout.c in Sources */,
E69BE5561B93FED300AFBA3F /* ijkinject.c in Sources */,
......@@ -794,6 +817,7 @@
E654EABE1B6B287400B0F2D0 /* image_convert.c in Sources */,
E654EAB61B6B286400B0F2D0 /* ffpipenode_ios_videotoolbox_vdec.m in Sources */,
E654EAA81B6B283D00B0F2D0 /* IJKAVPlayerLayerView.m in Sources */,
E68B7AC61C1E7F20001DE241 /* IJKSDLHudViewController.m in Sources */,
E654EACA1B6B288A00B0F2D0 /* ijksdl_vout_ios_gles2.m in Sources */,
E654EABA1B6B286B00B0F2D0 /* ffpipeline_ffplay.c in Sources */,
);
......
......@@ -94,6 +94,7 @@ typedef enum IJKLogLevel {
@property(nonatomic, readonly) CGFloat fpsInMeta;
@property(nonatomic, readonly) CGFloat fpsAtOutput;
@property(nonatomic) BOOL shouldShowHudView;
- (void)setOptionValue:(NSString *)value
forKey:(NSString *)key
......
......@@ -27,6 +27,7 @@
#import "IJKMediaPlayback.h"
#import "IJKMediaModule.h"
#import "IJKAudioKit.h"
#import "NSString+IJKMedia.h"
#include "string.h"
#include "ijkplayer/version.h"
......@@ -63,6 +64,9 @@ static const char *kIJKFFRequiredFFmpegVersion = "ff2.8--ijk0.4.1.1--dev0.3.3--r
BOOL _playingBeforeInterruption;
NSMutableArray *_registeredNotifications;
BOOL _shouldShowHudView;
NSTimer *_hudTimer;
}
@synthesize view = _view;
......@@ -175,6 +179,7 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
// init fields
_scalingMode = IJKMPMovieScalingModeAspectFit;
_shouldAutoplay = YES;
_shouldShowHudView = options.showHudView;
// init media resource
_urlString = aUrlString;
......@@ -192,6 +197,10 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
_glView = [[IJKSDLGLView alloc] initWithFrame:[[UIScreen mainScreen] bounds]
useRenderQueue:options.useRenderQueue];
_view = _glView;
[_glView setHudValue:nil forKey:@"scheme"];
[_glView setHudValue:nil forKey:@"host"];
[_glView setHudValue:nil forKey:@"path"];
[_glView setHudValue:nil forKey:@"ip"];
ijkmp_ios_set_glview(_mediaPlayer, _glView);
ijkmp_set_option(_mediaPlayer, IJKMP_OPT_CATEGORY_PLAYER, "overlay-format", "fcc-i420");
......@@ -247,6 +256,10 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
if (!_mediaPlayer)
return;
if (_urlString != nil) {
[self setHudUrl:_urlString];
}
[self setScreenOn:_keepScreenOnWhilePlaying];
ijkmp_set_data_source(_mediaPlayer, [_urlString UTF8String]);
......@@ -254,6 +267,37 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
ijkmp_prepare_async(_mediaPlayer);
}
- (void)setHudUrl:(NSString *)urlString
{
if ([[NSThread currentThread] isMainThread]) {
NSRange range = [urlString rangeOfString:@"://"];
if (range.location != NSNotFound) {
NSString *urlFullScheme = [urlString substringToIndex:range.location];
NSRange rangeOfLastScheme = [urlFullScheme rangeOfString:@":"
options:NSBackwardsSearch
range:NSMakeRange(0, range.location)];
if (rangeOfLastScheme.location != NSNotFound) {
NSString *urlExtra = [urlString substringFromIndex:rangeOfLastScheme.location + 1];
NSURL *url = [NSURL URLWithString:urlExtra];
[_glView setHudValue:urlFullScheme forKey:@"scheme"];
[_glView setHudValue:url.host forKey:@"host"];
[_glView setHudValue:url.path forKey:@"path"];
return;
}
}
NSURL *url = [NSURL URLWithString:urlString];
[_glView setHudValue:url.scheme forKey:@"scheme"];
[_glView setHudValue:url.host forKey:@"host"];
[_glView setHudValue:url.path forKey:@"path"];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self setHudUrl:urlString];
});
}
}
- (void)play
{
if (!_mediaPlayer)
......@@ -261,6 +305,7 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
[self setScreenOn:_keepScreenOnWhilePlaying];
[self startHudTimer];
ijkmp_start(_mediaPlayer);
}
......@@ -269,6 +314,7 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
if (!_mediaPlayer)
return;
[self stopHudTimer];
ijkmp_pause(_mediaPlayer);
}
......@@ -279,6 +325,7 @@ void IJKFFIOStatCompleteRegister(void (*cb)(const char *url,
[self setScreenOn:NO];
[self stopHudTimer];
ijkmp_stop(_mediaPlayer);
}
......@@ -405,6 +452,8 @@ inline static int getPlayerOption(IJKFFOptionCategory category)
{
if (!_mediaPlayer)
return;
[self stopHudTimer];
[self unregisterApplicationObservers];
[self setScreenOn:NO];
......@@ -579,6 +628,99 @@ inline static int getPlayerOption(IJKFFOptionCategory category)
return _glView.fps;
}
- (void)refreshHudView
{
if (_mediaPlayer == nil)
return;
int64_t vdec = ijkmp_get_property_int64(_mediaPlayer, FFP_PROP_INT64_VIDEO_DECODER, FFP_PROPV_DECODER_UNKNOWN);
float vdps = ijkmp_get_property_float(_mediaPlayer, FFP_PROP_FLOAT_VIDEO_DECODE_FRAMES_PER_SECOND, .0f);
float vfps = ijkmp_get_property_float(_mediaPlayer, FFP_PROP_FLOAT_VIDEO_OUTPUT_FRAMES_PER_SECOND, .0f);
switch (vdec) {
case FFP_PROPV_DECODER_VIDEOTOOLBOX:
[_glView setHudValue:@"VideoToolbox" forKey:@"vdec"];
break;
case FFP_PROPV_DECODER_AVCODEC:
[_glView setHudValue:[NSString stringWithFormat:@"avcodec %d.%d.%d",
LIBAVCODEC_VERSION_MAJOR,
LIBAVCODEC_VERSION_MINOR,
LIBAVCODEC_VERSION_MICRO]
forKey:@"vdec"];
break;
default:
[_glView setHudValue:@"N/A" forKey:@"vdec"];
break;
}
[_glView setHudValue:[NSString stringWithFormat:@"%.2f / %.2f", vdps, vfps] forKey:@"fps"];
int64_t vcacheb = ijkmp_get_property_int64(_mediaPlayer, FFP_PROP_INT64_VIDEO_CACHED_BYTES, 0);
int64_t acacheb = ijkmp_get_property_int64(_mediaPlayer, FFP_PROP_INT64_AUDIO_CACHED_BYTES, 0);
int64_t vcached = ijkmp_get_property_int64(_mediaPlayer, FFP_PROP_INT64_VIDEO_CACHED_DURATION, 0);
int64_t acached = ijkmp_get_property_int64(_mediaPlayer, FFP_PROP_INT64_AUDIO_CACHED_DURATION, 0);
int64_t vcachep = ijkmp_get_property_int64(_mediaPlayer, FFP_PROP_INT64_VIDEO_CACHED_PACKETS, 0);
int64_t acachep = ijkmp_get_property_int64(_mediaPlayer, FFP_PROP_INT64_AUDIO_CACHED_PACKETS, 0);
[_glView setHudValue:[NSString stringWithFormat:@"%"PRId64" ms, %"PRId64" bytes, %"PRId64" packets", vcached, vcacheb, vcachep]
forKey:@"v-cache"];
[_glView setHudValue:[NSString stringWithFormat:@"%"PRId64" ms, %"PRId64" bytes, %"PRId64" packets", acached, acacheb, acachep]
forKey:@"a-cache"];
float avdelay = ijkmp_get_property_float(_mediaPlayer, FFP_PROP_FLOAT_AVDELAY, .0f);
float avdiff = ijkmp_get_property_float(_mediaPlayer, FFP_PROP_FLOAT_AVDIFF, .0f);
[_glView setHudValue:[NSString stringWithFormat:@"%.3f %.3f", avdelay, -avdiff] forKey:@"delay"];
}
- (void)startHudTimer
{
if (!_shouldShowHudView)
return;
if (_hudTimer != nil)
return;
if ([[NSThread currentThread] isMainThread]) {
_hudTimer = [NSTimer scheduledTimerWithTimeInterval:.5f
target:self
selector:@selector(refreshHudView)
userInfo:nil
repeats:YES];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self startHudTimer];
});
}
}
- (void)stopHudTimer
{
if (_hudTimer == nil)
return;
if ([[NSThread currentThread] isMainThread]) {
[_hudTimer invalidate];
_hudTimer = nil;
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self stopHudTimer];
});
}
}
- (void)setShouldShowHudView:(BOOL)shouldShowHudView
{
_shouldShowHudView = shouldShowHudView;
if (shouldShowHudView)
[self startHudTimer];
else
[self stopHudTimer];
}
- (BOOL)shouldShowHudView
{
return _shouldShowHudView;
}
- (void)setPlaybackRate:(float)playbackRate
{
if (!_mediaPlayer)
......@@ -715,6 +857,7 @@ inline static void fillMetaInternal(NSMutableDictionary *meta, IjkMediaMeta *raw
_mediaMeta = newMediaMeta;
}
[self startHudTimer];
_isPreparedToPlay = YES;
[[NSNotificationCenter defaultCenter] postNotificationName:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:self];
......@@ -871,7 +1014,7 @@ int media_player_msg_loop(void* arg)
#pragma mark av_format_control_message
static int onInjectUrlOpen(id<IJKMediaUrlOpenDelegate> delegate, int type, void *data, size_t data_size)
static int onInjectUrlOpen(IJKFFMoviePlayerController *mpc, id<IJKMediaUrlOpenDelegate> delegate, int type, void *data, size_t data_size)
{
IJKAVInject_OnUrlOpenData *realData = data;
assert(realData);
......@@ -882,8 +1025,18 @@ static int onInjectUrlOpen(id<IJKMediaUrlOpenDelegate> delegate, int type, void
if (delegate == nil)
return 0;
NSString *urlString = [NSString stringWithUTF8String:realData->url];
NSURL *url = [NSURL URLWithString:urlString];
if ([url.scheme isEqualToString:@"tcp"] || [url.scheme isEqualToString:@"udp"]) {
if ([url.host ijk_isIpv4]) {
[mpc->_glView setHudValue:url.host forKey:@"ip"];
}
} else {
[mpc setHudUrl:urlString];
}
IJKMediaUrlOpenData *openData =
[[IJKMediaUrlOpenData alloc] initWithUrl:[NSString stringWithUTF8String:realData->url]
[[IJKMediaUrlOpenData alloc] initWithUrl:urlString
openType:(IJKMediaUrlOpenType)type
segmentIndex:realData->segment_index
retryCounter:realData->retry_counter];
......@@ -912,13 +1065,13 @@ static int ijkff_inject_callback(void *opaque, int message, void *data, size_t d
switch (message) {
case IJKAVINJECT_CONCAT_RESOLVE_SEGMENT:
return onInjectUrlOpen(mpc.segmentOpenDelegate, message, data, data_size);
return onInjectUrlOpen(mpc, mpc.segmentOpenDelegate, message, data, data_size);
case IJKAVINJECT_ON_TCP_OPEN:
return onInjectUrlOpen(mpc.tcpOpenDelegate, message, data, data_size);
return onInjectUrlOpen(mpc, mpc.tcpOpenDelegate, message, data, data_size);
case IJKAVINJECT_ON_HTTP_OPEN:
return onInjectUrlOpen(mpc.httpOpenDelegate, message, data, data_size);
return onInjectUrlOpen(mpc, mpc.httpOpenDelegate, message, data, data_size);
case IJKAVINJECT_ON_LIVE_RETRY:
return onInjectUrlOpen(mpc.liveOpenDelegate, message, data, data_size);
return onInjectUrlOpen(mpc, mpc.liveOpenDelegate, message, data, data_size);
default: {
return 0;
}
......
......@@ -69,5 +69,6 @@ struct IjkMediaPlayer;
-(void)setPlayerOptionIntValue: (int64_t)value forKey:(NSString *)key;
@property(nonatomic) BOOL useRenderQueue;
@property(nonatomic) BOOL showHudView;
@end
......@@ -51,6 +51,7 @@
[options setCodecOptionIntValue:IJK_AVDISCARD_NONREF forKey:@"skip_frame"];
options.useRenderQueue = NO;
options.showHudView = NO;
return options;
}
......
......@@ -327,7 +327,7 @@ void VTDecoderCallback(void *decompressionOutputRefCon,
goto failed;
}
ffp->vdps = SDL_SpeedSamplerAdd(&ctx->sampler, FFP_SHOW_VDPS_VIDEOTOOLBOX, "vdps[VideoToolbox]");
ffp->stat.vdps = SDL_SpeedSamplerAdd(&ctx->sampler, FFP_SHOW_VDPS_VIDEOTOOLBOX, "vdps[VideoToolbox]");
#ifdef FFP_VTB_DISABLE_OUTPUT
goto failed;
#endif
......
......@@ -45,8 +45,10 @@ static IJKFF_Pipenode *func_open_video_decoder(IJKFF_Pipeline *pipeline, FFPlaye
if (node == NULL) {
ALOGE("vtb fail!!! switch to ffmpeg decode!!!! \n");
node = ffpipenode_create_video_decoder_from_ffplay(ffp);
ffp->stat.vdec_type = FFP_PROPV_DECODER_AVCODEC;
opaque->is_videotoolbox_open = false;
} else {
ffp->stat.vdec_type = FFP_PROPV_DECODER_VIDEOTOOLBOX;
opaque->is_videotoolbox_open = true;
}
ffp_notify_msg2(ffp, FFP_MSG_VIDEO_DECODER_OPEN, opaque->is_videotoolbox_open);
......
......@@ -32,9 +32,11 @@
- (void) display: (SDL_VoutOverlay *) overlay;
- (UIImage*) snapshot;
- (void)setHudValue:(NSString *)value forKey:(NSString *)key;
@property(nonatomic,strong) NSLock *appActivityLock;
@property(nonatomic) CGFloat fps;
@property(nonatomic) CGFloat scaleFactor;
@property(nonatomic) BOOL shouldShowHudView;
@end
......@@ -30,7 +30,7 @@
#import "IJKSDLGLRenderNV12.h"
#include "ijksdl/ijksdl_timer.h"
#include "ijksdl/ios/ijksdl_ios.h"
#import "IJKSDLHudViewController.h"
static NSString *const g_vertexShaderString = IJK_SHADER_STRING
(
......@@ -184,6 +184,8 @@ static void mat4f_LoadOrtho(float left, float right, float bottom, float top, fl
BOOL _useRenderQueue;
dispatch_queue_t _renderQueue;
IJKSDLHudViewController *_hudViewController;
}
enum {
......@@ -225,6 +227,9 @@ static int g_ijk_gles_queue_spec_key;
_didSetupGL = NO;
[self setupGLOnce];
_hudViewController = [[IJKSDLHudViewController alloc] init];
[self addSubview:_hudViewController.tableView];
}
return self;
......@@ -411,6 +416,19 @@ static int g_ijk_gles_queue_spec_key;
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect selfFrame = self.frame;
CGRect newFrame = selfFrame;
newFrame.size.width = selfFrame.size.width * 1 / 3;
newFrame.origin.x = selfFrame.size.width * 2 / 3;
newFrame.size.height = selfFrame.size.height * 6 / 8;
newFrame.origin.y += selfFrame.size.height * 1 / 8;
_hudViewController.tableView.frame = newFrame;
_didRelayoutSubViews = YES;
}
......@@ -930,4 +948,26 @@ exit:
return image;
}
#pragma mark IJKFFHudController
- (void)setHudValue:(NSString *)value forKey:(NSString *)key
{
if ([[NSThread currentThread] isMainThread]) {
[_hudViewController setHudValue:value forKey:key];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self setHudValue:value forKey:key];
});
}
}
- (void)setShouldShowHudView:(BOOL)shouldShowHudView
{
_hudViewController.tableView.hidden = !shouldShowHudView;
}
- (BOOL)shouldShowHudView
{
return !_hudViewController.tableView.hidden;
}
@end
//
// IJKSDLHudViewCell.h
// IJKMediaPlayer
//
// Created by Zhang Rui on 15/12/14.
// Copyright © 2015年 bilibili. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface IJKSDLHudViewCell : UITableViewCell
- (id)init;
- (void)setHudValue:(NSString *)value forKey:(NSString *)key;
@end
//
// IJKSDLHudViewCell.m
// IJKMediaPlayer
//
// Created by Zhang Rui on 15/12/14.
// Copyright © 2015年 bilibili. All rights reserved.
//
#import "IJKSDLHudViewCell.h"
#define COLUMN_COUNT 2
#define CELL_MARGIN 8
@interface IJKSDLHudViewCell()
@end
@implementation IJKSDLHudViewCell
{
UILabel *_column[COLUMN_COUNT];
}
- (id)init
{
self = [super init];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.contentView.backgroundColor = [UIColor clearColor];
for (int i = 0; i < COLUMN_COUNT; ++i) {
_column[i] = [[UILabel alloc] init];
_column[i].textColor = [UIColor whiteColor];
_column[i].font = [UIFont fontWithName:@"Menlo" size:9];
[self.contentView addSubview:_column[i]];
}
}
return self;
}
- (void)setHudValue:(NSString *)value forKey:(NSString *)key
{
_column[0].text = key;
_column[1].text = value;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect parentFrame = self.contentView.frame;
CGRect newFrame = parentFrame;
CGFloat nextX = CELL_MARGIN;
newFrame.origin.x = nextX;
newFrame.size.width = parentFrame.size.width * 0.2;
_column[0].frame = newFrame;
nextX = newFrame.origin.x + newFrame.size.width + CELL_MARGIN;
newFrame.origin.x = nextX;
newFrame.size.width = parentFrame.size.width - nextX - CELL_MARGIN;
_column[1].frame = newFrame;
}
@end
//
// IJKSDLHudViewController.h
// IJKMediaPlayer
//
// Created by Zhang Rui on 15/12/14.
// Copyright © 2015年 bilibili. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface IJKSDLHudViewController : UITableViewController
- (id)init;
- (void)setHudValue:(NSString *)value forKey:(NSString *)key;
@end
//
// IJKSDLHudViewController.m
// IJKMediaPlayer
//
// Created by Zhang Rui on 15/12/14.
// Copyright © 2015年 bilibili. All rights reserved.
//
#import "IJKSDLHudViewController.h"
#import "IJKSDLHudViewCell.h"
@interface HudViewCellData : NSObject
@property(nonatomic) NSString *key;
@property(nonatomic) NSString *value;
@end
@implementation HudViewCellData
@end
@interface IJKSDLHudViewController() <UITableViewDataSource, UITableViewDelegate>
@end
@implementation IJKSDLHudViewController
{
NSMutableDictionary *_keyIndexes;
NSMutableArray *_hudDataArray;
}
- (id)init
{
self = [super init];
if (self) {
_keyIndexes = [[NSMutableDictionary alloc] init];
_hudDataArray = [[NSMutableArray alloc] init];
self.tableView.backgroundColor = [[UIColor alloc] initWithRed:.5f green:.5f blue:.5f alpha:.5f];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
return self;
}
- (void)setHudValue:(NSString *)value forKey:(NSString *)key
{
HudViewCellData *data = nil;
NSNumber *index = [_keyIndexes objectForKey:key];
if (index == nil) {
data = [[HudViewCellData alloc] init];
data.key = key;
[_keyIndexes setObject:[NSNumber numberWithUnsignedInteger:_hudDataArray.count]
forKey:key];
[_hudDataArray addObject:data];
} else {
data = [_hudDataArray objectAtIndex:[index unsignedIntegerValue]];
}
data.value = value;
[self.tableView reloadData];
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
assert(section == 0);
return _hudDataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
assert(indexPath.section == 0);
IJKSDLHudViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"hud"];
if (cell == nil) {
cell = [[IJKSDLHudViewCell alloc] init];
}
HudViewCellData *data = [_hudDataArray objectAtIndex:indexPath.item];
[cell setHudValue:data.value forKey:data.key];
return cell;
}
#pragma mark UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 20.f;
}
@end
//
// NSString+IJKMedia.h
// IJKMediaPlayer
//
// Created by Zhang Rui on 15/12/15.
// Copyright © 2015年 bilibili. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (IJKMedia)
- (BOOL) ijk_isIpv4;
@end
//
// NSString+IJKMedia.m
// IJKMediaPlayer
//
// Created by Zhang Rui on 15/12/15.
// Copyright © 2015年 bilibili. All rights reserved.
//
#import "NSString+IJKMedia.h"
@implementation NSString (IJKMedia)
- (BOOL) ijk_isIpv4
{
NSString *regexp =
@"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])$";
NSRange range = [self rangeOfString:regexp options:NSRegularExpressionSearch];
return range.location != NSNotFound;
}
@end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册