Commit 6d95c782 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

MacOSX/Framework: Support streamin media list.

parent d372e0d8
...@@ -78,7 +78,7 @@ static void * DestroySharedLibraryAtExit( void ) ...@@ -78,7 +78,7 @@ static void * DestroySharedLibraryAtExit( void )
const char * lib_vlc_params[] = { const char * lib_vlc_params[] = {
"-I", "dummy", "--vout=opengllayer", "-I", "dummy", "--vout=opengllayer",
"--no-video-title-show", "--no-sout-keep", "-vvv", "--encoder=ffmpeg" "--no-video-title-show", "--no-sout-keep", "-vvv"
//, "--control=motion", "--motion-use-rotate", "--video-filter=rotate" //, "--control=motion", "--motion-use-rotate", "--video-filter=rotate"
}; };
......
...@@ -90,6 +90,8 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * ...@@ -90,6 +90,8 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
newState = VLCMediaPlayerStatePaused; newState = VLCMediaPlayerStatePaused;
else if( event->type == libvlc_MediaInstanceReachedEnd ) else if( event->type == libvlc_MediaInstanceReachedEnd )
newState = VLCMediaPlayerStateStopped; newState = VLCMediaPlayerStateStopped;
else if( event->type == libvlc_MediaInstanceEncounteredError )
newState = VLCMediaPlayerStateError;
else else
{ {
NSLog(@"%s: Unknown event", __FUNCTION__); NSLog(@"%s: Unknown event", __FUNCTION__);
...@@ -416,8 +418,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * ...@@ -416,8 +418,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
- (void)setMedia:(VLCMedia *)value - (void)setMedia:(VLCMedia *)value
{ {
// We only know how to play media files...not media resources with subitems if (media != value)
if (media != value && [media subitems] == nil)
{ {
if (media && [media compare:value] == NSOrderedSame) if (media && [media compare:value] == NSOrderedSame)
return; return;
...@@ -480,7 +481,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * ...@@ -480,7 +481,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
- (void)stop - (void)stop
{ {
if( [NSThread isMainThread] ) if( 0 && [NSThread isMainThread] )
{ {
/* Hack because we create a dead lock here, when the vout is stopped /* Hack because we create a dead lock here, when the vout is stopped
* and tries to recontact us on the main thread */ * and tries to recontact us on the main thread */
...@@ -492,20 +493,13 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * ...@@ -492,20 +493,13 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
// Return if there is no media available or if the system is not in play status // Return if there is no media available or if the system is not in play status
// or pause status. // or pause status.
if (!media || (![self isPlaying] && [self state] != VLCMediaPlayerStatePaused)) if (!media)
return; return;
// The following is not implemented in the core, should I fix it or just libvlc_exception_t ex;
// compensate? libvlc_exception_init( &ex );
// libvlc_exception_t ex; libvlc_media_instance_stop((libvlc_media_instance_t *)instance, &ex);
// libvlc_exception_init( &ex ); catch_exception( &ex );
// libvlc_media_instance_stop((libvlc_media_instance_t *)instance, &ex);
// catch_exception( &ex );
// Pause and reposition to the begining of the stream.
[self pause];
[self setTime:0];
// TODO: Should we pause this or destroy the media instance so that it appears as being "stopped"?
} }
- (void)fastForward - (void)fastForward
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
{ {
if( self = [super init] ) if( self = [super init] )
{ {
options = [NSMutableDictionary dictionaryWithDictionary:dictionary]; options = [[NSMutableDictionary dictionaryWithDictionary:dictionary] retain];
} }
return self; return self;
} }
...@@ -51,10 +51,10 @@ ...@@ -51,10 +51,10 @@
{ {
return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys: return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys: [NSDictionary dictionaryWithObjectsAndKeys:
@"x264", @"videoCodec", @"mp4v", @"videoCodec",
@"768", @"videoBitrate", @"1024", @"videoBitrate",
@"mp4a", @"audioCodec", @"mp4a", @"audioCodec",
@"128", @"audioBitrate", @"192", @"audioBitrate",
@"2", @"channels", @"2", @"channels",
@"320", @"width", @"320", @"width",
@"240", @"canvasHeight", @"240", @"canvasHeight",
...@@ -70,6 +70,60 @@ ...@@ -70,6 +70,60 @@
] ]
]; ];
} }
+ (id)mpeg4StreamOutputWithFilePath:(NSString *)filePath
{
return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"mp4v", @"videoCodec",
@"1024", @"videoBitrate",
@"mp4a", @"audioCodec",
@"192", @"audioBitrate",
nil
], @"transcodingOptions",
[NSDictionary dictionaryWithObjectsAndKeys:
@"mp4", @"muxer",
@"file", @"access",
[filePath copy], @"destination", nil
], @"outputOptions",
nil
]
];
}
+ (id)streamOutputWithFilePath:(NSString *)filePath
{
return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"ps", @"muxer",
@"file", @"access",
[filePath copy], @"destination", nil
], @"outputOptions",
nil
]
];
}
+ (id)mpeg2StreamOutputWithFilePath:(NSString *)filePath;
{
return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"mp2v", @"videoCodec",
@"1024", @"videoBitrate",
@"mp2a", @"audioCodec",
@"128", @"audioBitrate",
@"Yes", @"audio-sync",
nil
], @"transcodingOptions",
[NSDictionary dictionaryWithObjectsAndKeys:
@"mpeg", @"muxer",
@"file", @"access",
[filePath copy], @"destination", nil
], @"outputOptions",
nil
]
];
}
@end @end
@implementation VLCStreamOutput (LibVLCBridge) @implementation VLCStreamOutput (LibVLCBridge)
...@@ -90,6 +144,8 @@ ...@@ -90,6 +144,8 @@
NSString * canvasHeight = [transcodingOptions objectForKey:@"canvasHeight"]; NSString * canvasHeight = [transcodingOptions objectForKey:@"canvasHeight"];
NSString * width = [transcodingOptions objectForKey:@"width"]; NSString * width = [transcodingOptions objectForKey:@"width"];
NSString * audioSync = [transcodingOptions objectForKey:@"audioSync"]; NSString * audioSync = [transcodingOptions objectForKey:@"audioSync"];
NSString * videoEncoder = [transcodingOptions objectForKey:@"videoEncoder"];
if( videoEncoder ) [subOptions addObject:[NSString stringWithFormat:@"venc=%@", videoEncoder]];
if( videoCodec ) [subOptions addObject:[NSString stringWithFormat:@"vcodec=%@", videoCodec]]; if( videoCodec ) [subOptions addObject:[NSString stringWithFormat:@"vcodec=%@", videoCodec]];
if( videoBitrate ) [subOptions addObject:[NSString stringWithFormat:@"vb=%@", videoBitrate]]; if( videoBitrate ) [subOptions addObject:[NSString stringWithFormat:@"vb=%@", videoBitrate]];
if( width ) [subOptions addObject:[NSString stringWithFormat:@"width=%@", width]]; if( width ) [subOptions addObject:[NSString stringWithFormat:@"width=%@", width]];
...@@ -110,7 +166,7 @@ ...@@ -110,7 +166,7 @@
NSString * destination = [outputOptions objectForKey:@"destination"]; NSString * destination = [outputOptions objectForKey:@"destination"];
NSString * url = [outputOptions objectForKey:@"url"]; NSString * url = [outputOptions objectForKey:@"url"];
NSString * access = [outputOptions objectForKey:@"access"]; NSString * access = [outputOptions objectForKey:@"access"];
if( muxer ) [subOptions addObject:[NSString stringWithFormat:@"muxer=%@", muxer]]; if( muxer ) [subOptions addObject:[NSString stringWithFormat:@"mux=%@", muxer]];
if( destination ) [subOptions addObject:[NSString stringWithFormat:@"dst=\"%@\"", [destination stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]]; if( destination ) [subOptions addObject:[NSString stringWithFormat:@"dst=\"%@\"", [destination stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]];
if( url ) [subOptions addObject:[NSString stringWithFormat:@"url=\"%@\"", [url stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]]; if( url ) [subOptions addObject:[NSString stringWithFormat:@"url=\"%@\"", [url stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]];
if( access ) [subOptions addObject:[NSString stringWithFormat:@"access=%@", access]]; if( access ) [subOptions addObject:[NSString stringWithFormat:@"access=%@", access]];
......
...@@ -9,9 +9,31 @@ ...@@ -9,9 +9,31 @@
#import "VLCStreamSession.h" #import "VLCStreamSession.h"
#import "VLCLibVLCBridging.h" #import "VLCLibVLCBridging.h"
@interface VLCStreamSession ()
@property (readwrite) BOOL isComplete;
@end
@implementation VLCStreamSession @implementation VLCStreamSession
@synthesize media=originalMedia; @synthesize media=originalMedia;
@synthesize streamOutput; @synthesize streamOutput;
@synthesize isComplete;
- (id)init
{
if( self = [super init] )
{
reattemptedConnections = 0;
[self addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];
self.isComplete = NO;
}
return self;
}
- (void)dealloc
{
[self removeObserver:self forKeyPath:@"state"];
[super dealloc];
}
+ (id)streamSession + (id)streamSession
{ {
...@@ -21,6 +43,7 @@ ...@@ -21,6 +43,7 @@
- (void)startStreaming; - (void)startStreaming;
{ {
self.isComplete = NO;
[self play]; [self play];
} }
...@@ -28,16 +51,19 @@ ...@@ -28,16 +51,19 @@
{ {
NSString * libvlcArgs; NSString * libvlcArgs;
if( self.drawable ) if( self.drawable )
{
libvlcArgs = [NSString stringWithFormat:@"duplicate{dst=display,dst=\"%@\"}",[streamOutput representedLibVLCOptions]]; libvlcArgs = [NSString stringWithFormat:@"duplicate{dst=display,dst=\"%@\"}",[streamOutput representedLibVLCOptions]];
else
libvlcArgs = [streamOutput representedLibVLCOptions];
if( libvlcArgs )
{
[super setMedia: [VLCMedia mediaWithMedia:originalMedia andLibVLCOptions:
[NSDictionary dictionaryWithObject: libvlcArgs forKey: @"sout"]]];
} }
else else
{ {
libvlcArgs = [streamOutput representedLibVLCOptions]; [super setMedia: self.media];
} }
[super setMedia: [VLCMedia mediaWithMedia:originalMedia andLibVLCOptions:
[NSDictionary dictionaryWithObject: libvlcArgs
forKey: @"sout"]]];
[super play]; [super play];
} }
...@@ -56,13 +82,40 @@ ...@@ -56,13 +82,40 @@
return @"Converting..."; return @"Converting...";
} }
+ (NSSet *)keyPathsForValuesAffectingIsComplete + (NSSet *)keyPathsForValuesAffectingEncounteredError
{ {
return [NSSet setWithObjects:@"playing", @"state", @"position", nil]; return [NSSet setWithObjects:@"state", nil];
} }
- (BOOL)isComplete - (BOOL)encounteredError;
{ {
return ([self position] == 1.0 || [self state] == VLCMediaPlayerStateEnded || ([self state] == VLCMediaPlayerStateStopped && self.media)); return ([self state] == VLCMediaPlayerStateError);
} }
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"state"])
{
if( (([self position] == 1.0 || [self state] == VLCMediaPlayerStateEnded || ([self state] == VLCMediaPlayerStateStopped && self.media)) ||
[self encounteredError] ) && ![super.media subitems] )
{
self.isComplete = YES;
return;
}
if( reattemptedConnections > 4 )
return;
/* Our media has in fact gained subitems, let's change our playing media */
if( [[super.media subitems] count] > 0 )
{
[self stop];
self.media = [[super.media subitems] mediaAtIndex:0];
[self play];
reattemptedConnections++;
}
return;
}
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
@end @end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment