Browse Source

MacOSX/Framework: Add VLCStreamSession, VLCStreamOutput to allow streaming/exporting.

Pierre d'Herbemont 17 years ago
parent
commit
9f84d217b7

+ 9 - 0
Headers/Internal/VLCLibVLCBridging.h

@@ -24,6 +24,7 @@
 
 #import "VLCLibrary.h"
 #import "VLCMediaListAspect.h"
+#import "VLCStreamOutput.h"
 
 /**
  * Bridges functionality between libvlc and VLCMediaList implementation.
@@ -83,6 +84,8 @@ extern void __catch_exception( void * e, const char * function, const char * fil
  */
 - (id)initWithLibVLCMediaDescriptor:(void *)md;
 
++ (id)mediaWithMedia:(VLCMedia *)media andLibVLCOptions:(NSDictionary *)options;
+
 /**
  * Returns the receiver's internal media descriptor pointer.
  * \return The receiver's internal media descriptor pointer.
@@ -100,6 +103,8 @@ extern void __catch_exception( void * e, const char * function, const char * fil
  * \param value
  */
 - (void)setLength:(VLCTime *)value;
+
+
 @end
 
 /**
@@ -171,3 +176,7 @@ extern void __catch_exception( void * e, const char * function, const char * fil
  */
 - (id)initWithLibrary:(VLCLibrary *)library;
 @end
+
+@interface VLCStreamOutput (LibVLCBridge)
+- (NSString *)representedLibVLCOptions;
+@end

+ 2 - 0
Headers/Public/VLCKit.h

@@ -35,6 +35,8 @@
 #import <VLCKit/VLCTime.h>
 #import <VLCKit/VLCVideoView.h>
 #import <VLCKit/VLCVideoLayer.h>
+#import <VLCKit/VLCStreamSession.h>
+#import <VLCKit/VLCStreamOutput.h>
 
 @class VLCMedia;
 @class VLCMediaLibrary;

+ 26 - 0
Headers/Public/VLCStreamOutput.h

@@ -0,0 +1,26 @@
+//
+//  VLCStreamOutput.h
+//  VLCKit
+//
+//  Created by Pierre d'Herbemont on 1/12/08.
+//  Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+extern NSString * VLCDefaultStreamOutputRTSP;
+extern NSString * VLCDefaultStreamOutputRTP;
+extern NSString * VLCDefaultStreamOutputRTP;
+
+@interface VLCStreamOutput : NSObject {
+    NSMutableDictionary * options;
+}
+
+- (id)initWithOptionDictionary:(NSDictionary *)dictionary;
++ (id)streamOutputWithOptionDictionary:(NSDictionary *)dictionary;
+
++ (id)rtpBroadcastStreamOutputWithSAPAnnounce:(NSString *)announceName;
++ (id)rtpBroadcastStreamOutput;
++ (id)ipodStreamOutputWithFilePath:(NSString *)filePath;
+
+@end

+ 27 - 0
Headers/Public/VLCStreamSession.h

@@ -0,0 +1,27 @@
+//
+//  VLCStreamSession.h
+//  VLCKit
+//
+//  Created by Pierre d'Herbemont on 1/12/08.
+//  Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <VLCKit/VLCStreamOutput.h>
+#import <VLCKit/VLCMediaPlayer.h>
+#import <VLCKit/VLCMedia.h>
+
+
+@interface VLCStreamSession : VLCMediaPlayer {
+    VLCStreamOutput * streamOutput;
+    VLCMedia * originalMedia;
+}
+
++ (id)streamSession;
+
+@property (retain) VLCMedia * media;
+@property (retain) VLCStreamOutput * streamOutput;
+@property (readonly) BOOL isComplete;
+
+- (void)startStreaming;
+@end

+ 2 - 1
Sources/VLCLibrary.m

@@ -78,7 +78,8 @@ static void * DestroySharedLibraryAtExit( void )
         
         const char * lib_vlc_params[] = { 
             "-I", "dummy", "--vout=opengllayer", 
-            "--no-video-title-show"
+            "--no-video-title-show", "--no-sout-keep", "-vvv", "--encoder=ffmpeg"
+            //, "--control=motion", "--motion-use-rotate", "--video-filter=rotate"
         };
         
         instance = (void *)libvlc_new( sizeof(lib_vlc_params)/sizeof(lib_vlc_params[0]), lib_vlc_params, &ex );

+ 13 - 0
Sources/VLCMedia.m

@@ -350,6 +350,19 @@ static void HandleMediaSubItemAdded(const libvlc_event_t * event, void * self)
 {
     return p_md;
 }
+
++ (id)mediaWithMedia:(VLCMedia *)media andLibVLCOptions:(NSDictionary *)options
+{
+    libvlc_media_descriptor_t * p_md;
+    p_md = libvlc_media_descriptor_duplicate( [media libVLCMediaDescriptor] );
+    for( NSString * key in [options allKeys] )
+    {
+        NSLog(@"Adding %@", [NSString stringWithFormat:@"--%@ %@", key, [options objectForKey:key]]);
+        libvlc_media_descriptor_add_option(p_md, [[NSString stringWithFormat:@"%@=#%@", key, [options objectForKey:key]] UTF8String], NULL);
+    }
+    return [VLCMedia mediaWithLibVLCMediaDescriptor:p_md];
+}
+
 @end
 
 /******************************************************************************

+ 138 - 0
Sources/VLCStreamOutput.m

@@ -0,0 +1,138 @@
+//
+//  VLCStreamOutput.m
+//  VLCKit
+//
+//  Created by Pierre d'Herbemont on 1/12/08.
+//  Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import "VLCStreamOutput.h"
+#import "VLCLibVLCBridging.h"
+
+
+@implementation VLCStreamOutput
+- (id)initWithOptionDictionary:(NSDictionary *)dictionary
+{
+    if( self = [super init] )
+    {
+        options = [NSMutableDictionary dictionaryWithDictionary:dictionary];
+    }
+    return self;
+}
+- (NSString *)description
+{
+    return [self representedLibVLCOptions];
+}
++ (id)streamOutputWithOptionDictionary:(NSDictionary *)dictionary
+{
+    return [[[self alloc] initWithOptionDictionary:dictionary] autorelease];
+}
++ (id)rtpBroadcastStreamOutputWithSAPAnnounce:(NSString *)announceName
+{
+    return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
+                                            [NSDictionary dictionaryWithObjectsAndKeys:
+                                                @"ts", @"muxer",
+                                                @"file", @"access",
+                                                @"sap", @"sdp",
+                                                [announceName copy], @"name",
+                                                @"239.255.1.1", @"destination", nil
+                                            ], @"rtpOptions",
+                                            nil
+                                            ]
+                                        ];
+}
+
++ (id)rtpBroadcastStreamOutput
+{
+    return [self rtpBroadcastStreamOutputWithSAPAnnounce:@"Helloworld!"];
+}
+
++ (id)ipodStreamOutputWithFilePath:(NSString *)filePath
+{
+    return [self streamOutputWithOptionDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
+                                            [NSDictionary dictionaryWithObjectsAndKeys:
+                                                @"x264", @"videoCodec",
+                                                @"768",  @"videoBitrate",
+                                                @"mp4a", @"audioCodec",
+                                                @"128", @"audioBitrate",
+                                                @"2",   @"channels",
+                                                @"320", @"width",
+                                                @"240", @"canvasHeight",
+                                                @"Yes", @"audio-sync",
+                                                nil
+                                            ], @"transcodingOptions",
+                                            [NSDictionary dictionaryWithObjectsAndKeys:
+                                                @"mp4", @"muxer",
+                                                @"file", @"access",
+                                                [filePath copy], @"destination", nil
+                                            ], @"outputOptions",
+                                            nil
+                                            ]
+                                        ];
+}
+@end
+
+@implementation VLCStreamOutput (LibVLCBridge)
+- (NSString *)representedLibVLCOptions
+{
+    NSString * representedOptions;
+    NSMutableArray * subOptions = [NSMutableArray array];
+    NSMutableArray * optionsAsArray = [NSMutableArray array];
+    NSDictionary * transcodingOptions = [options objectForKey:@"transcodingOptions"];
+    if( transcodingOptions )
+    {
+        NSString * videoCodec = [transcodingOptions objectForKey:@"videoCodec"];
+        NSString * audioCodec = [transcodingOptions objectForKey:@"audioCodec"];
+        NSString * videoBitrate = [transcodingOptions objectForKey:@"videoBitrate"];
+        NSString * audioBitrate = [transcodingOptions objectForKey:@"audioBitrate"];
+        NSString * channels = [transcodingOptions objectForKey:@"channels"];
+        NSString * height = [transcodingOptions objectForKey:@"height"];
+        NSString * canvasHeight = [transcodingOptions objectForKey:@"canvasHeight"];
+        NSString * width = [transcodingOptions objectForKey:@"width"];
+        NSString * audioSync = [transcodingOptions objectForKey:@"audioSync"];
+        if( videoCodec )   [subOptions addObject:[NSString stringWithFormat:@"vcodec=%@", videoCodec]];
+        if( videoBitrate ) [subOptions addObject:[NSString stringWithFormat:@"vb=%@", videoBitrate]];
+        if( width ) [subOptions addObject:[NSString stringWithFormat:@"width=%@", width]];
+        if( height ) [subOptions addObject:[NSString stringWithFormat:@"height=%@", height]];
+        if( canvasHeight ) [subOptions addObject:[NSString stringWithFormat:@"canvas-height=%@", canvasHeight]];
+        if( audioCodec )   [subOptions addObject:[NSString stringWithFormat:@"acodec=%@", audioCodec]];
+        if( audioBitrate ) [subOptions addObject:[NSString stringWithFormat:@"ab=%@", audioBitrate]];
+        if( channels ) [subOptions addObject:[NSString stringWithFormat:@"channels=%@", channels]];
+        if( audioSync ) [subOptions addObject:[NSString stringWithFormat:@"audioSync", width]];
+        [optionsAsArray addObject: [NSString stringWithFormat:@"transcode{%@}", [subOptions componentsJoinedByString:@","]]];
+        [subOptions removeAllObjects];
+    }
+    
+    NSDictionary * outputOptions = [options objectForKey:@"outputOptions"];
+    if( outputOptions )
+    {
+        NSString * muxer = [outputOptions objectForKey:@"muxer"];
+        NSString * destination = [outputOptions objectForKey:@"destination"];
+        NSString * url = [outputOptions objectForKey:@"url"];
+        NSString * access = [outputOptions objectForKey:@"access"];
+        if( muxer )       [subOptions addObject:[NSString stringWithFormat:@"muxer=%@", 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]];
+        [optionsAsArray addObject:[NSString stringWithFormat:@"std{%@}", [subOptions componentsJoinedByString:@","]]];
+        [subOptions removeAllObjects];
+    }
+
+    NSDictionary * rtpOptions = [options objectForKey:@"rtpOptions"];
+    if( rtpOptions )
+    {
+        NSString * muxer = [rtpOptions objectForKey:@"muxer"];
+        NSString * destination = [rtpOptions objectForKey:@"destination"];
+        NSString * sdp = [rtpOptions objectForKey:@"sdp"];
+        NSString * name = [rtpOptions objectForKey:@"name"];
+        if( muxer )       [subOptions addObject:[NSString stringWithFormat:@"muxer=%@", muxer]];
+        if( destination ) [subOptions addObject:[NSString stringWithFormat:@"dst=%@", destination]];
+        if( sdp )      [subOptions addObject:[NSString stringWithFormat:@"sdp=%@", sdp]];
+        if( name )      [subOptions addObject:[NSString stringWithFormat:@"name=\"%@\"", name]];
+        [optionsAsArray addObject:[NSString stringWithFormat:@"rtp{%@}", [subOptions componentsJoinedByString:@","]]];
+        [subOptions removeAllObjects];
+    }
+    representedOptions = [optionsAsArray componentsJoinedByString:@":"];
+    return representedOptions;
+}
+@end

+ 68 - 0
Sources/VLCStreamSession.m

@@ -0,0 +1,68 @@
+//
+//  VLCStreamSession.m
+//  VLCKit
+//
+//  Created by Pierre d'Herbemont on 1/12/08.
+//  Copyright 2008 __MyCompanyName__. All rights reserved.
+//
+
+#import "VLCStreamSession.h"
+#import "VLCLibVLCBridging.h"
+
+@implementation VLCStreamSession
+@synthesize media=originalMedia;
+@synthesize streamOutput;
+
++ (id)streamSession
+{
+    return [[[self alloc] init] autorelease];
+}
+
+
+- (void)startStreaming;
+{
+    [self play];
+}
+
+- (void)play;
+{
+    NSString * libvlcArgs;
+    if( self.drawable )
+    {
+        libvlcArgs = [NSString stringWithFormat:@"duplicate{dst=display,dst=\"%@\"}",[streamOutput representedLibVLCOptions]];
+    }
+    else
+    {
+        libvlcArgs = [streamOutput representedLibVLCOptions];
+    }
+    [super setMedia: [VLCMedia mediaWithMedia:originalMedia andLibVLCOptions:
+                            [NSDictionary dictionaryWithObject: libvlcArgs
+                                                        forKey: @"sout"]]];
+    [super play];
+}
+
++ (NSSet *)keyPathsForValuesAffectingDescription
+{
+    return [NSSet setWithObjects:@"isCompleted", @"state", nil];
+}
+
+- (NSString *)description
+{
+    if([self isComplete])
+        return @"Done.";
+    else if([self state] == VLCMediaPlayerStateError)
+        return @"Error while Converting. Open Console.app to diagnose.";
+    else
+        return @"Converting...";
+}
+
++ (NSSet *)keyPathsForValuesAffectingIsComplete
+{
+    return [NSSet setWithObjects:@"playing", @"state", @"position", nil];
+}
+
+- (BOOL)isComplete
+{
+    return ([self position] == 1.0 || [self state] == VLCMediaPlayerStateEnded || ([self state] == VLCMediaPlayerStateStopped && self.media));
+}
+@end

+ 32 - 0
VLCKit.xcodeproj/project.pbxproj

@@ -49,6 +49,10 @@
 /* Begin PBXBuildFile section */
 		6303C43A0CF45CAE0000ECC8 /* VLCMediaListAspect.m in Sources */ = {isa = PBXBuildFile; fileRef = 6303C4390CF45CAE0000ECC8 /* VLCMediaListAspect.m */; };
 		6303C43C0CF45CC30000ECC8 /* VLCMediaListAspect.h in Headers */ = {isa = PBXBuildFile; fileRef = 6303C43B0CF45CC30000ECC8 /* VLCMediaListAspect.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		632A0E850D3835C400AFC99B /* VLCStreamSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 632A0E830D3835C400AFC99B /* VLCStreamSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		632A0E860D3835C400AFC99B /* VLCStreamSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 632A0E840D3835C400AFC99B /* VLCStreamSession.m */; };
+		632A0EC30D38392E00AFC99B /* VLCStreamOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 632A0EC10D38392E00AFC99B /* VLCStreamOutput.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		632A0EC40D38392E00AFC99B /* VLCStreamOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 632A0EC20D38392E00AFC99B /* VLCStreamOutput.m */; };
 		6341FCAF0D2C0929002A97B7 /* VLCVideoLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6341FCAE0D2C0929002A97B7 /* VLCVideoLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		6341FCB10D2C0936002A97B7 /* VLCVideoLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6341FCB00D2C0936002A97B7 /* VLCVideoLayer.m */; };
 		637CFB940D2D280900A041B6 /* VLCLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 637CFB930D2D280800A041B6 /* VLCLibrary.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -118,6 +122,10 @@
 		63030CC70CCA652C0088ECD1 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; name = Info.plist; path = Resources/Info.plist; sourceTree = "<group>"; };
 		6303C4390CF45CAE0000ECC8 /* VLCMediaListAspect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCMediaListAspect.m; sourceTree = "<group>"; };
 		6303C43B0CF45CC30000ECC8 /* VLCMediaListAspect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCMediaListAspect.h; path = Public/VLCMediaListAspect.h; sourceTree = "<group>"; };
+		632A0E830D3835C400AFC99B /* VLCStreamSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCStreamSession.h; path = Public/VLCStreamSession.h; sourceTree = "<group>"; };
+		632A0E840D3835C400AFC99B /* VLCStreamSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCStreamSession.m; sourceTree = "<group>"; };
+		632A0EC10D38392E00AFC99B /* VLCStreamOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCStreamOutput.h; path = Public/VLCStreamOutput.h; sourceTree = "<group>"; };
+		632A0EC20D38392E00AFC99B /* VLCStreamOutput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCStreamOutput.m; sourceTree = "<group>"; };
 		6341FCAE0D2C0929002A97B7 /* VLCVideoLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCVideoLayer.h; path = Public/VLCVideoLayer.h; sourceTree = "<group>"; };
 		6341FCB00D2C0936002A97B7 /* VLCVideoLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCVideoLayer.m; sourceTree = "<group>"; };
 		637CFB930D2D280800A041B6 /* VLCLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLCLibrary.h; path = Public/VLCLibrary.h; sourceTree = "<group>"; };
@@ -219,6 +227,7 @@
 				EF78BD450CAEEFF600354E6E /* VLCVideoView.m */,
 				EF78BD440CAEEFF600354E6E /* VLCTime.m */,
 				EF73118F0CB5797B009473B4 /* VLCAudio.m */,
+				632A0F7B0D38F78500AFC99B /* Stream */,
 			);
 			path = Sources;
 			sourceTree = "<group>";
@@ -250,6 +259,24 @@
 			name = "Other Sources";
 			sourceTree = "<group>";
 		};
+		632A0F7B0D38F78500AFC99B /* Stream */ = {
+			isa = PBXGroup;
+			children = (
+				632A0EC20D38392E00AFC99B /* VLCStreamOutput.m */,
+				632A0E840D3835C400AFC99B /* VLCStreamSession.m */,
+			);
+			name = Stream;
+			sourceTree = "<group>";
+		};
+		632A0F7C0D38F79200AFC99B /* Stream */ = {
+			isa = PBXGroup;
+			children = (
+				632A0E830D3835C400AFC99B /* VLCStreamSession.h */,
+				632A0EC10D38392E00AFC99B /* VLCStreamOutput.h */,
+			);
+			name = Stream;
+			sourceTree = "<group>";
+		};
 		637CFB960D2D281900A041B6 /* Internal */ = {
 			isa = PBXGroup;
 			children = (
@@ -283,6 +310,7 @@
 				EF78BD1A0CAEEEE700354E6E /* VLCVideoView.h */,
 				EF78BD190CAEEEE700354E6E /* VLCTime.h */,
 				EF73118E0CB5797B009473B4 /* VLCAudio.h */,
+				632A0F7C0D38F79200AFC99B /* Stream */,
 			);
 			path = Headers;
 			sourceTree = "<group>";
@@ -309,6 +337,8 @@
 				6341FCAF0D2C0929002A97B7 /* VLCVideoLayer.h in Headers */,
 				637CFB940D2D280900A041B6 /* VLCLibrary.h in Headers */,
 				A7A0CEA40D2EF13000F2C039 /* VLCVideoCommon.h in Headers */,
+				632A0E850D3835C400AFC99B /* VLCStreamSession.h in Headers */,
+				632A0EC30D38392E00AFC99B /* VLCStreamOutput.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -467,6 +497,8 @@
 				637D5ADC0CF6F2720073EA45 /* VLCMediaDiscoverer.m in Sources */,
 				6341FCB10D2C0936002A97B7 /* VLCVideoLayer.m in Sources */,
 				A7A0CEA50D2EF13000F2C039 /* VLCVideoCommon.m in Sources */,
+				632A0E860D3835C400AFC99B /* VLCStreamSession.m in Sources */,
+				632A0EC40D38392E00AFC99B /* VLCStreamOutput.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};