2

I have been playing a bit with the Chromecast SDK those days. What I am currently trying to do is to send a UIImage (for example a photo taken with the iPhone) on the TV using the Chromecast.

I am able to load "external" image using an URL but I can't figure out how to send a locally stored image!

So is there a way to send it using base64 encoding, or to set up a stream, or even to mirror the screen ? I am a bit lost, if someone could give me a hint or some sample code, that'll be great !

tanou
  • 1,083
  • 2
  • 13
  • 33

3 Answers3

0

You can host a small web server in your app and then provide the URL to that server to the Chromecast receiver app to load the photos from your device. The Cast protocol channel is not designed to handle large binary transfers.

Leon Nicholls
  • 4,623
  • 2
  • 16
  • 17
  • It is possible to host a web server inside an app ? Can you explain, briefly, how this can be made (just to point me in the right direction)? – tanou Jun 18 '14 at 06:55
  • Check out, for example, this project: https://github.com/robbiehanson/CocoaHTTPServer – Ali Naddaf Aug 18 '14 at 14:29
0

Building up on responses provided by Leon and Alok, i.e. serving images from your iOS device over HTTP using Cocoa HTTP server, you can find an example on at GitHub with detailed explanation in this blog post.

Also don't forget that to be served to your ChromeCast, you will need to enable CORS.

In short, and once you have added Cocoa HTTP Server to your project, you can

  1. subclass HTTPDataResponse as follows in order to enable CORS

CamCaptureDataResponse.h

#import "HTTPDataResponse.h"

@interface CamCaptureDataResponse : HTTPDataResponse

@end

CamCaptureDataResponse.m #import "CamCaptureDataResponse.h"

@implementation CamCaptureDataResponse

-(NSDictionary*)httpHeaders {
    return @{
             @"Access-Control-Allow-Origin":@"*",
             @"Access-Control-Allow-Methods":@"GET,PUT,POST,DELETE",
             @"Access-Control-Allow-Headers":@"Content-Type"
             };
}

@end
  1. Use this new DataResponse class in your own request handler by subclassing HTTPConnection

CamCaptureConnection.h

#import "HTTPConnection.h"

@interface CamCaptureConnection : HTTPConnection

@end

CamCaptureConnection.m

#import "CamCaptureConnection.h"
#import "CamCaptureHTTPServer.h"
#import "CamCaptureDataResponse.h"

@implementation CamCaptureConnection

-(NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:  (NSString *)path {
    NSArray* pathComponents = [path componentsSeparatedByString:@"/"];

    if ([pathComponents count] < 2) {
        return [[CamCaptureDataResponse alloc] initWithData:[@"ERROR" dataUsingEncoding:NSUTF8StringEncoding]];
    }

    NSString *command = [pathComponents objectAtIndex:1];

    if ([command isEqualToString:@"PING"]) {
        return [[CamCaptureDataResponse alloc] initWithData:[@"PONG"     dataUsingEncoding:NSUTF8StringEncoding]];
    }

    if ([command isEqualToString:@"PIC"]) {
        // Change the following line with whichever image you want to serve to your ChromeCast!
        NSData *imageData = UIImageJPEGRepresentation([CamCaptureHttpServer instance].captureImage, 0.3); 

        if (imageData) {
            return [[CamCaptureDataResponse alloc] initWithData:imageData];
        } else {
            return [[CamCaptureDataResponse alloc] initWithData:[@"NO_IMAGE" dataUsingEncoding:NSUTF8StringEncoding]];
        }
    }

    return [[CamCaptureDataResponse alloc] initWithData:[@"ERROR_UNKNOWN_COMMAND" dataUsingEncoding:NSUTF8StringEncoding]];
}

@end
  1. Then before you start, your web server, first register your new connection class as follows

    NSError *error;
    httpServer = [[CamCaptureHttpServer alloc] init];
    [httpServer setConnectionClass:[CamCaptureConnection class]];
    [httpServer setType:@"_http._tcp."];
    [httpServer setPort:1234];
    [httpServer start:&error];
    
-1

Yes ! you can use CocoaHTTPServer is a small, lightweight, embeddable HTTP server for Mac OS X or iOS applications.

#import "iPhoneHTTPServerAppDelegate.h"
#import "iPhoneHTTPServerViewController.h"
#import "HTTPServer.h"
#import "DDLog.h"
#import "DDTTYLogger.h"

// Log levels: off, error, warn, info, verbose
static const int ddLogLevel = LOG_LEVEL_VERBOSE;


@implementation iPhoneHTTPServerAppDelegate

@synthesize window;
@synthesize viewController;

- (void)startServer
{
    // Start the server (and check for problems)

    NSError *error;
    if([httpServer start:&error])
    {
        DDLogInfo(@"Started HTTP Server on port %hu", [httpServer listeningPort]);
    }
    else
    {
        DDLogError(@"Error starting HTTP Server: %@", error);
    }
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Configure our logging framework.
    // To keep things simple and fast, we're just going to log to the Xcode console.
    [DDLog addLogger:[DDTTYLogger sharedInstance]];

    // Create server using our custom MyHTTPServer class
    httpServer = [[HTTPServer alloc] init];

    // Tell the server to broadcast its presence via Bonjour.
    // This allows browsers such as Safari to automatically discover our service.
    [httpServer setType:@"_http._tcp."];

    // Normally there's no need to run our server on any specific port.
    // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime.
    // However, for easy testing you may want force a certain port so you can just hit the refresh button.
    // [httpServer setPort:12345];

    // Serve files from our embedded Web folder
    NSString *webPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Web"];
    DDLogInfo(@"Setting document root: %@", webPath);

    [httpServer setDocumentRoot:webPath];

    [self startServer];

    // Add the view controller's view to the window and display.
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];

    return YES;
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [self startServer];
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // There is no public(allowed in AppStore) method for iOS to run continiously in the background for our purposes (serving HTTP).
    // So, we stop the server when the app is paused (if a users exits from the app or locks a device) and
    // restart the server when the app is resumed (based on this document: http://developer.apple.com/library/ios/#technotes/tn2277/_index.html )

    [httpServer stop];
}



@end