MacOSX/Framework: Add VLCStreamSession, VLCStreamOutput to allow streaming/exporting.
authorPierre d'Herbemont <pdherbemont@videolan.org>
Sun, 13 Jan 2008 00:57:29 +0000 (00:57 +0000)
committerPierre d'Herbemont <pdherbemont@videolan.org>
Sun, 13 Jan 2008 00:57:29 +0000 (00:57 +0000)
extras/MacOSX/Framework/Headers/Internal/VLCLibVLCBridging.h
extras/MacOSX/Framework/Headers/Public/VLCKit.h
extras/MacOSX/Framework/Headers/Public/VLCStreamOutput.h [new file with mode: 0644]
extras/MacOSX/Framework/Headers/Public/VLCStreamSession.h [new file with mode: 0644]
extras/MacOSX/Framework/Sources/VLCLibrary.m
extras/MacOSX/Framework/Sources/VLCMedia.m
extras/MacOSX/Framework/Sources/VLCStreamOutput.m [new file with mode: 0644]
extras/MacOSX/Framework/Sources/VLCStreamSession.m [new file with mode: 0644]
extras/MacOSX/Framework/VLCKit.xcodeproj/project.pbxproj

index 2e9156c..cc94d51 100644 (file)
@@ -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
index ee72850..8a0769e 100644 (file)
@@ -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;
diff --git a/extras/MacOSX/Framework/Headers/Public/VLCStreamOutput.h b/extras/MacOSX/Framework/Headers/Public/VLCStreamOutput.h
new file mode 100644 (file)
index 0000000..9a0ce55
--- /dev/null
@@ -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
diff --git a/extras/MacOSX/Framework/Headers/Public/VLCStreamSession.h b/extras/MacOSX/Framework/Headers/Public/VLCStreamSession.h
new file mode 100644 (file)
index 0000000..6dd6ed8
--- /dev/null
@@ -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
index f3a42c5..1b46fb1 100644 (file)
@@ -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 );
index 2ab4214..792109d 100644 (file)
@@ -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
 
 /******************************************************************************
diff --git a/extras/MacOSX/Framework/Sources/VLCStreamOutput.m b/extras/MacOSX/Framework/Sources/VLCStreamOutput.m
new file mode 100644 (file)
index 0000000..2655176
--- /dev/null
@@ -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
diff --git a/extras/MacOSX/Framework/Sources/VLCStreamSession.m b/extras/MacOSX/Framework/Sources/VLCStreamSession.m
new file mode 100644 (file)
index 0000000..ab35858
--- /dev/null
@@ -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
index 0ebfadd..83ca72a 100644 (file)
 /* 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, ); }; };
                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>"; };
                                EF78BD450CAEEFF600354E6E /* VLCVideoView.m */,
                                EF78BD440CAEEFF600354E6E /* VLCTime.m */,
                                EF73118F0CB5797B009473B4 /* VLCAudio.m */,
+                               632A0F7B0D38F78500AFC99B /* Stream */,
                        );
                        path = Sources;
                        sourceTree = "<group>";
                        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 = (
                                EF78BD1A0CAEEEE700354E6E /* VLCVideoView.h */,
                                EF78BD190CAEEEE700354E6E /* VLCTime.h */,
                                EF73118E0CB5797B009473B4 /* VLCAudio.h */,
+                               632A0F7C0D38F79200AFC99B /* Stream */,
                        );
                        path = Headers;
                        sourceTree = "<group>";
                                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;
                };
                                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;
                };