Commit fb2de8af authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

MacOSX/Framework: Support streamin media list.

parent 18a6697d
......@@ -78,7 +78,7 @@ static void * DestroySharedLibraryAtExit( void )
const char * lib_vlc_params[] = {
"-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"
};
......
......@@ -90,6 +90,8 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
newState = VLCMediaPlayerStatePaused;
else if( event->type == libvlc_MediaInstanceReachedEnd )
newState = VLCMediaPlayerStateStopped;
else if( event->type == libvlc_MediaInstanceEncounteredError )
newState = VLCMediaPlayerStateError;
else
{
NSLog(@"%s: Unknown event", __FUNCTION__);
......@@ -416,8 +418,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
- (void)setMedia:(VLCMedia *)value
{
// We only know how to play media files...not media resources with subitems
if (media != value && [media subitems] == nil)
if (media != value)
{
if (media && [media compare:value] == NSOrderedSame)
return;
......@@ -480,7 +481,7 @@ static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void *
- (void)stop
{
if( [NSThread isMainThread] )
if( 0 && [NSThread isMainThread] )
{
/* Hack because we create a dead lock here, when the vout is stopped
* and tries to recontact us on the main thread */
......@@ -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
// or pause status.
if (!media || (![self isPlaying] && [self state] != VLCMediaPlayerStatePaused))
if (!media)
return;
// The following is not implemented in the core, should I fix it or just
// compensate?
// libvlc_exception_t ex;
// libvlc_exception_init( &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"?
libvlc_exception_t ex;
libvlc_exception_init( &ex );
libvlc_media_instance_stop((libvlc_media_instance_t *)instance, &ex);
catch_exception( &ex );
}
- (void)fastForward
......
......@@ -15,7 +15,7 @@
{
if( self = [super init] )
{
options = [NSMutableDictionary dictionaryWithDictionary:dictionary];
options = [[NSMutableDictionary dictionaryWithDictionary:dictionary] retain];
}
return self;
}
......@@ -51,10 +51,10 @@
{
return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
@"x264", @"videoCodec",
@"768", @"videoBitrate",
@"mp4v", @"videoCodec",
@"1024", @"videoBitrate",
@"mp4a", @"audioCodec",
@"128", @"audioBitrate",
@"192", @"audioBitrate",
@"2", @"channels",
@"320", @"width",
@"240", @"canvasHeight",
......@@ -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
@implementation VLCStreamOutput (LibVLCBridge)
......@@ -90,6 +144,8 @@
NSString * canvasHeight = [transcodingOptions objectForKey:@"canvasHeight"];
NSString * width = [transcodingOptions objectForKey:@"width"];
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( videoBitrate ) [subOptions addObject:[NSString stringWithFormat:@"vb=%@", videoBitrate]];
if( width ) [subOptions addObject:[NSString stringWithFormat:@"width=%@", width]];
......@@ -110,7 +166,7 @@
NSString * destination = [outputOptions objectForKey:@"destination"];
NSString * url = [outputOptions objectForKey:@"url"];
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( url ) [subOptions addObject:[NSString stringWithFormat:@"url=\"%@\"", [url stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]];
if( access ) [subOptions addObject:[NSString stringWithFormat:@"access=%@", access]];
......
......@@ -9,9 +9,31 @@
#import "VLCStreamSession.h"
#import "VLCLibVLCBridging.h"
@interface VLCStreamSession ()
@property (readwrite) BOOL isComplete;
@end
@implementation VLCStreamSession
@synthesize media=originalMedia;
@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
{
......@@ -21,6 +43,7 @@
- (void)startStreaming;
{
self.isComplete = NO;
[self play];
}
......@@ -28,16 +51,19 @@
{
NSString * libvlcArgs;
if( self.drawable )
{
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
{
libvlcArgs = [streamOutput representedLibVLCOptions];
[super setMedia: self.media];
}
[super setMedia: [VLCMedia mediaWithMedia:originalMedia andLibVLCOptions:
[NSDictionary dictionaryWithObject: libvlcArgs
forKey: @"sout"]]];
[super play];
}
......@@ -56,13 +82,40 @@
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
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