Closed linked67 closed 8 years ago
Not sure, can you provide some log with timestamp?
The log i have in Xcode don't has timestamp, it comes from ffmpeg i think. I use this code to stop / start the player:
-(void)closePlayer{
for (UIView *subview in [self.movieView subviews]) {
[subview removeFromSuperview];
}
if (self.player) {
if ([self.player isPlaying] || [self.player isPreparedToPlay]) {
[self.player stop];
}
// [self.player shutdown];
}
//[self removeMovieNotificationObservers];
}
- (void)start {
NSURL *theMovieURL = [NSURL URLWithString:@"myurl" ];
[IJKFFMoviePlayerController setLogReport:YES];
self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:theMovieURL withOptions:nil];
self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
self.player.view.frame = self.view.bounds;
self.view.autoresizesSubviews = YES;
[self.movieView addSubview:self.player.view];
[self installMovieNotificationObservers];
[self.player prepareToPlay];
[self.player play];
}
And i only see this on stop:
ijkmp_stop()
ijkmp_stop()=0
aout_close_audio()
The 10 or 15s come from me watching the clock after many try. As you can see, i have commented some part. When i don't call shutdown, it takes a lot more time to close the stream. Maybe 20s or 30s, i have to test more to find the exact timing.
And this is what i have when i try to open a stream too fast:
ijkmp_set_format_callback(0x1001e0b54, 0x1741d0d10)
ijkmp_set_format_callback()=void
ijkmp_set_auto_play_on_prepared(1)
ijkmp_set_auto_play_on_prepared()=void
2015-05-12 14:16:15.905 myapp[24654:3688387] OK setup GL
ijkmp_ios_set_view(glView=0x154e54fe0)
ijkmp_ios_set_view(glView=0x154e54fe0)=void
ijkmp_set_overlay_format(I420(0x30323449))
ijkmp_set_overlay_format()=void
ijkmp_set_data_source(url="rtsp://theurl")
ijkmp_set_data_source(url="rtsp://theurl")=0
ijkmp_set_format_option(safe, 0)
ijkmp_set_format_option()=void
ijkmp_prepare_async()
ijkmp_prepare_async()=0
ijkmp_start()
ijkmp_start()=-3
[rtsp @ 0x1550b7c00] SDP:
v=0
o=leCDN 1431432975 1431432975 IN IP4 kapoueh.proxad.net
s=unknown
i=unknown
c=IN IP4 0.0.0.0
t=0 0
m=video 0 RTP/AVP 33
a=control:rtsp://theurl
[udp @ 0x154d25140] end receive buffer size reported is 65536
[udp @ 0x154d41da0] end receive buffer size reported is 65536
[rtsp @ 0x1550b7c00] method SETUP failed: 453 Not Enough Bandwidth
Change the line below in ff_ffplay.c to enable more log.
av_lockmgr_register(lockmgr);
if (g_ffmpeg_global_use_log_report) {
av_log_set_callback(ffp_log_callback_report);
} else {
// av_log_set_callback(ffp_log_callback_brief);
av_log_set_callback(ffp_log_callback_report);
}
Or, would you please provide some playable stream for me to debug? I don't have much idea about rtsp.
VLC has its own rtsp implement. I think the problem could be in libavformat/rtsp.c
I don't see more log like something that could happen after the delay where i can switch to another stream.
It would be great if you could test my stream but it's a media box under my TV and even if i setup everyting to give you access from outside, my upload bandwidth is too low.
Maybe you can test with some rtsp stream that we can easy find on the web ? They won't say you that a stream is already open because you switch to another URL and the new link will open with a new player instance while in the background the other is slowly closed. Maybe you can just catch what is going slow when a rtsp stream is closed.
Here is the first lisk i have found: rtsp://46.249.213.87/broadcast/bollywoodgossip-tablet.3gp
Let me know if you need more
Can't be reproduced with this url, maybe it's too slow from my network.
Can you pause the debug in xcode immediately after stop, to see where it is blocked in thread named "read_thread"?
If you mean the ff_read thread, it's closed after 1s but not immediately after my close method call. I have put a sleep(1) and a breakpoint to see it.
If i put a sleep(30) between the close method and the new player init, it can play the second stream. With 25s in sleep, it doesn't work, it's too early.
I have notice that the only suspect thread i have see when the breakpoint stop just after the 30s sleep is: [self performSelectorOnMainThread:@selector(shutdownClose:) withObject:self waitUntilDone:YES];
It's alive before or after the 30s but dissapear once the new stream play. I have use your demo code to make the tests to have very few threads. The other threads open don't show something usefull (for me), only 2 lines like: __workq_kernelreturn start_wqthread
Modify the shutdown method as below, and see where it's blocked when you call shutdown.
- (void)shutdown
{
if (!_mediaPlayer)
return;
[self unregisterApplicationObservers];
[self setScreenOn:NO];
ijkmp_stop(_mediaPlayer);
ijkmp_shutdown(_mediaPlayer);
ijkmp_dec_ref_p(&_mediaPlayer);
}
After some other tests, sleep(29) is too early too while sleep(30) works.
I have take some screenshots to compare the different thread between 29 and 35 seconds after the close call and before i start to init a new player. With you modified shutdown, it's a bit more clear, there is less thread open.
The only difference bewteen a 5s and a 35s sleep is 2 thread with the same content:
Thread 5
__workq_kernreturn
start_wqthread
Thread 6
__workq_kernreturn
start_wqthread
I don't know what it means or how to use it. When i click on the first line (__workq_kernreturn) it display this:
libsystem_kernel.dylib`__workq_kernreturn:
0x11468c940 <+0>: movl $0x2000170, %eax
0x11468c945 <+5>: movq %rcx, %r10
0x11468c948 <+8>: syscall
-> 0x11468c94a <+10>: jae 0x11468c954 ; <+20>
0x11468c94c <+12>: movq %rax, %rdi
0x11468c94f <+15>: jmp 0x114687c53 ; cerror_nocancel
0x11468c954 <+20>: retq
0x11468c955 <+21>: nop
0x11468c956 <+22>: nop
0x11468c957 <+23>: nop
The second (start_wqthread):
libsystem_pthread.dylib`start_wqthread:
0x1146bb400 <+0>: pushq %rbp
0x1146bb401 <+1>: movq %rsp, %rbp
0x1146bb404 <+4>: subq $0x18, %rsp
0x1146bb408 <+8>: callq 0x1146bd35e ; _pthread_wqthread
0x1146bb40d <+13>: leave
0x1146bb40e <+14>: retq
0x1146bb40f <+15>: nop
Maybe the stream is closed on the device side and we see nothing interesting that remain but it looks like there is a "hey server, close the stream now" missing and the server just wait a 30s timeout before it close itself because there is no more traffic on this stream.
I'm not a network expert but it's the feel i have.
I'm not a network expert, too. :) Take a look at libavformat/rtsp.c.
Well after some tests if i wait for a couple of seconds before i press stop and put a sleep(10), i no more see the thread 5 and 6. But if i resume it, the server still say me it's already open.
The open thread list is exaclty the same if i wait 10s or 35s. First case don't work, too early, second work. That make me think the same as my previous command, some command to validate the close should be missing before the phone close the stream.
try this patch ( it's very old)
commit c973c2d9fa43b5f9dc1d0602b930e424971158ed
Author: GoogleGeek ffmpeg@gmail.com
Date: Fri Dec 26 19:27:22 2014 +0800
make stop operation ASAP
diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c
index 0dec497..cae73cb 100644
--- a/ijkmedia/ijkplayer/ff_ffplay.c
+++ b/ijkmedia/ijkplayer/ff_ffplay.c
@@ -2551,6 +2551,11 @@ static int read_thread(void *arg)
} else {
ffp->error = 0;
}
+
//we abort ASAP.
if (is->abort_request)
break;
if (eof) {
ffp_toggle_buffering(ffp, 0);
SDL_Delay(1000);
diff --git a/ijkmedia/ijksdl/android/android_audiotrack.c b/ijkmedia/ijksdl/android/android_audiotrack.c
index 5ae5768..9b7ebcc 100644
--- a/ijkmedia/ijksdl/android/android_audiotrack.c
+++ b/ijkmedia/ijksdl/android/android_audiotrack.c
@@ -442,6 +442,14 @@ void SDL_Android_AudioTrack_flush(JNIEnv env, SDL_Android_AudioTrack atrack)
void SDL_Android_AudioTrack_stop(JNIEnv env, SDL_Android_AudioTrack atrack)
{
SDLTRACE("SDL_Android_AudioTrack_stop");
SDL_Android_AudioTrack_flush(env, atrack);
(*env)->CallVoidMethod(env, atrack->thiz, g_clazz.stop);
if ((*env)->ExceptionCheck(env)) {
ALOGE("SDL_Android_AudioTrack_stop: stop: Exception:");
@@ -454,6 +462,7 @@ void SDL_Android_AudioTrack_stop(JNIEnv env, SDL_Android_AudioTrack atrack)
void SDL_Android_AudioTrack_release(JNIEnv env, SDL_Android_AudioTrack atrack)
{
SDLTRACE("SDL_Android_AudioTrack_release");
SDL_Android_AudioTrack_stop(env, atrack);
(*env)->CallVoidMethod(env, atrack->thiz, g_clazz.release);
if ((*env)->ExceptionCheck(env)) {
ALOGE("SDL_Android_AudioTrack_release: release: Exception:");
On Wed, May 13, 2015 at 4:39 PM, linked67 notifications@github.com wrote:
Well after some tests if i wait for a couple of seconds before i press stop and put a sleep(10), i no more see the thread 5 and 6. But if i resume it, the server still say me it's already open.
The open thread list is exaclty the same if i wait 10s or 35s. First case don't work, too early, second work. That make me think the same as my previous command, some command to validate the close should be missing before the phone close the stream.
Reply to this email directly or view it on GitHub https://github.com/Bilibili/ijkplayer/issues/225#issuecomment-101575182.
Founder of http://LiveKings.com
I have run instrument and have found that when i stop the stream at 10 seconds and just wait for allocations to move, something happens at 30s (only 20s more, weird). There is a few malloc and one has responsible caller: __net_helper_get_connection_block_invoke_3
And another: -[OS_xpc_connection _xref_dispose]
And another: _xpc_connection_dispose
It's in this order, maybe it can help you. Something is closed after a while.
I'll try your patch now.
I just have add these lines to patch it since the other looks for android:
if (is->abort_request)
break;
It does not change anything.
You can test with the url i have give you before: rtsp://46.249.213.87/broadcast/bollywoodgossip-tablet.3gp
Use the demo code on github with this URL and replace the ClickOnPause method with this:
- (IBAction)onClickPause:(id)sender
{
[self closePlayer];
}
-(void)closePlayer{
if (self.player) {
if ([self.player isPlaying] || [self.player isPreparedToPlay]) {
[self.player stop];
}
[self.player shutdown];
}
[self removeMovieNotificationObservers];
}
And comment the line 80 in IJKMediaControl.m to remove some noise because of the refresh timer. Now, start the project with allocating instrument. Record reference count and all alocations type.
Start the record, wait until 10s, the stream should be launched, and press the pause button twice because we have removed the refresh control. Let it run until 50s and see that something happens at 30s and 40s. We can see some allocation moving at 30s with xpc connection dispose but for 40s it display nothing even if i have see some move. Maybe a time glitch for this last.
This way you could test yourself and win some time.
I think the xpc connection that intrument talk about should dispose instantly instead of waiting so long. But i don't have deep understanding enough of this player to know where i should look to fix this.
You should look into libavformat/rtsp.c, FFmpeg does all the IO stuff.
Have you find some time since to check it with any rtsp stream in the way i have say just above ?
Not, yet. Actually, not on top of my to-do list.
I think it's very likely an FFmpeg issue. Try ffplay on your pc directly.
Well, still the same problem with latest build. Would be nice to find a solution to close the stream with no delay.
Add some log in libavformat/tcp.c, to see when and how it is closed.
I have to use UDP connection, if i try this:
av_dict_set(&ffp->format_opts, "rtsp_transport", "tcp", 0);
The device that act as server say me it's unsupported. With this it's fine:
av_dict_set(&ffp->format_opts, "rtsp_transport", "udp", 0);
In other words, should i really log tcp.c file even with a UDP connection ?
Then log udp
Feel free to reopen if any more question.
Hi,
I have a rtsp server that can stream only 1 stream on the same time.
When i try to call stop or shutdown, i have to wait around 10 or 15 seconds before i can init a new player. If i init the player before this time, the server say me that there is already a stream open.
What can i do either to switch on the fly without needing to init a new player or have a message that it's ok ? I don't see MPMoviePlaybackStateStopped, only MPMoviePlaybackStatePlaying or MPMoviePlaybackStatePaused.
It would be nice to not wait the 10 or 15s, with vlc i don't have this problem.