Digital Media • 41:16
With the introduction of QuickTime Streaming Server 2, Apple has moved to a plug-in architecture that allows developers to extend, enhance, and add functionality. Learn about the QuickTime Streaming Server Module API and how you can use it to create your own plug-in modules.
Speaker: Denis Serenyl
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Please welcome Denis Sereny. Hi, everyone. Welcome to Session 301, QuickTime Streaming Server. My name is Denis Sereny. I'm a software engineer on the QuickTime Streaming Server team at Apple. And I'm going to talk to you a lot about QuickTime Streaming Server. For those of you who have been at the previous two sessions, it's time to shift gears a little bit.
We talked a lot about authoring, a lot about integrating QuickTime into your application. Now I'm going to talk about a whole new class of applications. Applications over on the server side. Things like integrating QuickTime Streaming Server into a database or doing custom user interfaces or doing monitoring tools for your streaming clients. So a whole new set of applications. And I'm going to talk for a while and then at the end I'll stick around and we can do some Q&A if you guys have questions.
Okay, so. The main gist of the presentation, I'm going to talk to you a lot about QTSS API, which is a server-side API we introduced with QuickTime Streaming Server 2. And it's a fully, it's a big C API that allows you to do a lot of things and allows you to extend QuickTime Streaming Server in a lot of ways and a lot of cool applications. I'll show some demos of things that you can do with QTSS API. And I don't know, many of you, maybe you don't think that servers are cool.
When I get through these demos, hopefully you'll think that servers are pretty cool and that you can do a lot with QTSS. So first, though, I'm going to talk to you a little bit about QuickTime Streaming Server 2, just the features, and then I'll also tell you a little bit about things that we're working on for future releases of the server, give you a little preview of that.
OK, so QuickTime Streaming Server 2 is, of course, we're talking only about RTSP and RTP streaming here. It handles real-time streaming protocol and real-time transport protocol. And those are two IETF standard protocols. One of the great things is that QuickTime Streaming is just really the only major completely standards-based streaming solution out there. And we're really trying to make sure that QuickTime Streaming can interoperate with all the tools that support these standards. So that's really great. And the two major features of QuickTime Streaming Server are that it supports reflecting of live broadcasts.
In the previous session, you saw Kevin talking a little bit about encoders and broadcasters. And in one slide, he showed QTSS sitting in between an encoder and clients. So you can use QTSS to reflect a live broadcast out to a whole slew of RTSP clients. QTSS manages the complexity of all the RTSP transactions of lots of clients coming in and going out. And then it also supports video on demand. So that means you can take hinted QuickTime movies, drop them in the media folder on the server. And the server allows clients to connect over RTSP and view them in streaming.
One of the things that we added for QuickTime Streaming Server 2 is that we also support RTSP tunneled through HTTP. That's different than HTTP progressive downloads. It's true streaming, but it's using the HTTP protocol. And why is that important? Well, after we did 1.0 version of the server, we found that a lot of people who are behind corporate firewalls or HTTP proxies or network address translators couldn't get access to QuickTime Streaming because they only, on their network topology, they could only get access to HTTP stuff.
So because we support tunneling RTSP into HTTP, it means that if you deploy a QuickTime Streaming Server and if you deploy QuickTime Streaming Server, you can get access to HTTP stuff. So if you deploy a QuickTime Streaming Server and you deploy a QuickTime Streaming Server, you'll know that all clients will be able to get access to QuickTime Streaming no matter what kind of network they're on.
So that's really important. We also added password security. This is something that I'll be demoing a little bit later on. It's something that we implemented using QTSS API completely. And it's a really important component for doing pay-per-view. So that's a really neat thing. And then also the unicast to multicast relay. Kevin told you a little bit about multicast.
We talked about multicast in the previous presentation. One problem with multicast that he touched on is just the fact that it's not universally deployed on the internet. So on a lot of networks, they do have multicast, but only on pieces of the network, or multicast is only good in certain areas. If you put a QTSS machine as a relay at the border points between unicast and multicast, it can translate between unicast and multicast and back again.
And that allows you to utilize multicast where it is available. And multicast is really good to take advantage of because there's so much bandwidth savings. There's a lot of people that can only do really high bit rate live presentations using multicast because otherwise there would be just not enough bandwidth.
OK. Now, of course, we're working on lots of stuff for the future. There's two things that I want to tell you about. One big thing is web administration. We want to make sure that QTSS, in addition to being the most powerful streaming server out there, is the easiest streaming server to set up and the easiest streaming server to manage, to monitor all of your clients, and that everyone will be able to do that easily, remotely.
And also, as part of implementing that web administration interface, we're using QTSS API and we're writing an administration protocol module. Well, what does that mean? This module that's on the server will support an administration protocol that you as developers, or anyone as a developer, can utilize for writing a custom administration tool.
There are so many things out there that site administration... that streaming site administrators need to monitor, and they need to do it in so many different ways that, although we're going to try and cover as many bases as we can, we recognize that with streaming moving as fast as it does, we just can't cover everything.
So, we want to make it as easy as possible for third parties to tie into the server, and we think that if we provide a protocol like this, then they'll be able to write custom tools, and so that's a really great opportunity to even to sell those tools. So, it's a really great money-making opportunity, and in fact, there's tons of great money-making opportunities with QTSS, and I'll tell you a little about some more later on.
Okay, now one of the, really the most awesome thing about this project and working on this project is that it's totally open source. From day one when we shipped QTSS 1.0, we put all of the source out there. And that was a little bit more than a year ago. Since then, the entire streaming server team has really invested a lot in working with the open source community and making sure that we're able to get the right kind of content out there.
We're not just taking the open source name, that we're really doing everything out in the open and just investing in making this open source project work. And it's worked really well, actually. And we've done a lot better, actually, since starting out. We've started to add a lot more platforms.
And we've also tried to make sure that all of the platforms that we can compile on, we support really well. And so we've actually done internal testing of Darwin's streaming server on different platforms. And we've also released binaries of the server running on different platforms. So right now, we support Mac OS X server, of course. And we've added, since 1.0, we added Linux, FreeBSD, Solaris.
We recently released a Solaris binary. And we just announced support for Windows NT server and Windows 2000 server. Those binaries are not available yet. But we're still doing internal testing. But because we're open source, you can actually get access to that code. And if you have Visual C++, you have a Windows machine, you can check out the open source CVS and get the entire source repository and compile that using Visual C++. So that's really neat.
We're doing a lot of our development right now using that open source CVS repository. So if you're daring, you can check it out. You can check out our latest development versions that we're checking code into all the time. And of course, you shouldn't really do that and expect to actually deploy it, because it may not work. But it's just neat that we're doing all this development out in the open. So because of this open source thing, I really haven't heard of another streaming server that is open source.
So I can really say that we are just the most extensible streaming server out there. We give it away. We give all the source code away. It's just a huge firepower. It's just a huge fire sale. It's really great to work on this project because of that. And so developers can just go in there, modify the code, and do whatever they want with it.
And now we've added this QTSS API. When we first started out with the open source project, we took a good look at other successful open source projects because we wanted to emulate as much as possible what they've done in order to make their project successful. And of course, really the most successful server open source project is the Apache project. The Apache group, Apache is the most popular web server out there, and it's really one of the best known open source projects.
And so we took a look at the Apache server, and yeah, it's open source, and that's really great, but in addition to being open source, they also provide one of the most popular web server APIs available, the Apache API. And that really helps their development process because open source developers, because they have this API which is documented and which is relatively static, developers can go in and they can do a lot of work.
And so they can go in and modify Apache using the API and not really have to worry about the server as a whole, all the things that Apache is doing. They just have to worry about their particular little feature. And so it makes the open source project much more organized and much more focused. And so that's one thing that I'm really going to drive home as far as QTSS API. It makes developing in the open source framework much easier because there is this organization. Thank you.
OK, so I've talked a lot about QTSS API. Let me go into it in more detail now. And it's a C language programming interface. You can also-- we use a lot of C++ in our own modules, so you can use C++ as well. And it allows developers to add custom modules to the server.
Now these modules can, much like Apache modules, can either be compiled directly into the server, so you can write a module, modify the server internals slightly in order to get it to build inside the server, and release a monolithic server with your module added to it. And as an alternative, something that we're really encouraging module developers to take advantage of as much as possible, is you can package up modules as a separate shared library, or say on Windows, a DLL.
And in order to do that-- and when that happens, you have a separate piece of code, your module, and you can drop that into a QTSS modules folder. The server doesn't have to be recompiled at all. It just-- when it's starting up, it checks the QTSS modules folder and loads whatever modules happen to be there. So that's a really easy way to make a module and make it easily deployable.
So it provides separation, simplification, durability. Again, touching on the benefits that were realized by the Apache project, when you want to add a feature, say tying QuickTime Streaming Server into a proprietary database backend or something, you don't have to worry about the fact that QTSS has all these threads running, and there's all this network traffic going on, and there's like 100 classes or something in the server.
And we're modifying them all the time because we're adding these features. You don't have to worry about that because we have this API which is well documented, and it's durable. So moving forward for QTSS 3.0 or 4.0 or 5, you won't have to modify your module because it's an API that's backwards compatible as well. So that's a really big benefit. Okay.
How is the API useful? What can you do with it? Well, there are just tons of applications. We provided so many hooks in the server that are exposed through this module API. Things like logging. So if you have a custom log format and a custom tool that takes advantage of it, you can use QTSS API to have it log in a custom way.
Different file formats. So of course, QTSS out of the box supports hinted QuickTime movies. Now you can provide a plug-in that supports whatever file format you want. Status Reporting. Real-time statistics is something that, again and again, is something that's so important to administrators. You can run a module in the server that uses some back-end protocol and reports to a viewer, a real-time viewer of some kind.
[Transcript missing]
And then finally, server administration. If, again, you know, getting back to our administration protocol module, you can control the server in however you want and provide a custom interface for controlling QTSS. So there's tons of things. And, I mean, this is really just a great opportunity because the server is free, the server is open source, and we're making all these efforts to allow people to write modules very easily. And those modules can be sold for money. So, I mean, it's just a great opportunity.
So how do we know that QTSS API is really useful, and how do we know that it really works? The great thing is that when we developed QTSS 2.0, we integrated this API. We decided to take all of the features that we had in QTSS 1.0 and put them in QTSS API modules. And all of the features that we added to QTSS 2.0, we also put in QTSS API modules.
And so when we were done with the server, we had, I think, something like 15 modules that we ship along with the server. And some of those we provided compiled in so that people can't, like, accidentally turn off hinted QuickTime file serving if they mess around with their modules folder. But some of them we provided as separate binaries. For instance, the password security stuff, we recognize that probably, you know, that doesn't concern everyone. So we provided those as separate binaries.
So we really... ate our own dog food on this API. And so we really know that for all of these applications that I'm talking about, it can really be used and it's a really powerful tool. In fact, really, if you take all of the modules out of the server that we shipped, really the server doesn't do anything. It's basically just a framework that provides this API to these modules. So another thing that we know is that modules perform very well. QTSS, there's these... there's these numbers that we talk... these performance numbers that we talk about.
We support 2,000 low bitrate modem stream clients simultaneously. And those numbers were generated not through some optimized code path through the server that's tailored around the benchmark. It's... those numbers were generated by using the reflector module that I was talking about or using the hinted QuickTime movie file. So we know that if you choose to implement a feature for QTSS using the module API, that you won't be sacrificing anything with performance because we know that the API performs really well.
OK, so I told you a lot about the API from a high level. Let me just go over and show you a little bit about what it can do. I've got-- Oh, I've got the server up over here on this monitor, but I need a client machine over here so that I can show the server talking to the client. And that should be demo machine number-- oh, wait. It fell asleep. That's all. There we go.
Um, okay, so I've got a Mac OS X server machine over here. We aren't aquized yet, but at least, uh... Okay, so we've got the server running over here and just has Streaming Server done starting up. And over on this machine over here, I've got a client that's ready to connect and watch a movie coming off the server. So let me just do that. And it's asleep, so it's still waking up. Here we go, connecting, negotiating. Here we go, connecting. And that was coming off this server here. Now let me just bring down the server. You can just go Control-C. Oh, oops.
There we go. So, and I've got this folder here. It's in... on this drive in user ESPIN, and it's in this QTSS modules folder. So that's the folder that the server looks for QTSS API modules in. And I've got this demo authorization module, and let me just drag that into the modules folder.
This demo authorization module works really similar to the access module that I was telling you about that uses QT access files in order to do password security. Now when I go back and try and watch that movie again, I've got to go to a different port because I was using that port before. Now I've got to enter a password. If I enter something that's garbage, it says, "No way, you can't do that." I've got a user set up, Denis. I can't know what my password is.
And so by dragging that module into the modules folder, I added a new feature to the server. I added password security. So the server read that when the server was starting up, and the module handled denying access to that client. Okay, so that's modules as a separate binary.
Now, if I didn't want to provide that module as a separate binary, As I was telling you, you can package modules, both as separate binaries, and compile them directly into the server. So I've got a different version of the server that I compiled with the demo authorization module inside of it.
So let me start that server up. There's nothing in the modules folder. When I start up the client again, I'm going Well, I guess you're just going to have to trust me on it. So if the server was up, for some reason it's not up. Let me just try once more.
If the server was up and running, then you'd see the same behaviors that it was showing when I had the demo authorization module in the modules folder. And that was, it would be denying access to users unless they had name and password, and that's because I compiled that module directly into the server.
Back to slides. You know what? I think I know why this is happening. Anyone from the audience? I think it's because that machine has got the same IP address. So... Well, I'll keep on going, and if I've got problems with later demos, then I don't know what I'll do. I'll have to reboot the machine.
So how was that demo authorization module built? As you saw, it was built in two different ways. Using the QTSS API SDK is what you need to do if you want to build a module as a separate binary. So, and what that SDK includes is a .h file with just the QTSS API headers in it and a stub library that you need to link your QTSS API module as a shared library or whatever. You link it against that stub library and the SDK includes full documentation on the API.
Now, if you want to do it compiled into the server, then you need to have a copy of the server source code, and then you just take the server and make changes internally in the server in order to compile directly in. And those changes that you need to make in the server are documented in the QTSS API documentation, so you can find out what you need to do if you want to compile it directly into the server.
But one neat thing about this process is that the module code doesn't have to be changed if you want to build it as a shared library or compile it directly into the server. So when you're developing your module, when you're developing your feature, you don't have to really decide how it's going to be packaged.
That's one thing that's important for us when we're developing our modules internally. We don't really want to have to decide how it's going to be packaged. We don't really want to decide until the last minute whether we package them up as a separate binary or not. So because we don't have to change the code, we don't really have to make that decision until the last minute.
OK, so now that I've shown you a little bit about the API, let's dive into some of the API concepts. There are really four major concepts that we're introducing with QTSS API. And they are roles, which are just the framework that allow modules to get invoked. The server has a list of well-known roles that the server invokes modules in, and modules play these roles.
Callbacks are just the function calls in the server that modules make. And then there are QTSS API objects, which is the generic data passing mechanism in QTSS API. And streams are the way that modules communicate directly to the client. And the demo authorization module used all four of these concepts. So as I go through each one, I'll show you some source code for what was in the demo authorization module. And I'll show you how the demo authorization module works. authorization module utilizes these concepts.
So the first one is roles. Now roles are really similar to if you've dealt with other server APIs or other APIs in general. Apache calls them handlers. Modules play a role. There's a list of well-known roles in the API, things like initialization and the demo authorization module uses the authorization role in order to authorize clients. And modules provide a role handler, which is just a function, basically, and that function gets called when that situation comes up and then the module code executes. And from that code, then modules can make callbacks and control the server that way.
So here is just the source code in the demo authorization module talking about roles. This is a function called register, which is the role handler for the register role. It's the first role that gets called by the server when the server is starting up, and every QTSS API module must handle this role. Denis Serenyl One of the only things that modules need to do from inside this role is just tell the server what other roles it wants to play. It does that by making this add role callback.
And so the demo authorization module here is telling it that it wants to play the initialize role, and that is just a role that gets called immediately after the register role. And modules can do one-time initialization tasks that way. It also wants to be called in the reread preferences role, and that's a role that gets invoked whenever the server is told to reread its preferences.
And then finally, the RTSP Authorize role. That gets invoked on every single RTSP request to the server. And from inside that role, a module can say whether the client should be allowed or denied. And so that's how the demo authorization module told the server to deny access to clients sometimes.
And then finally, the QTSS RTSP Session object contains information related specifically to the RTSP control connections, so things like that TCP IP address and what port that is happening on, something like that. And then finally, the one that was utilized by the demo authorization module before, the QTSS RTSP request object, which contains things that are particular to a given RTSP request, like what RTSP method was being used. Is it describe or set up or tear down? Is it, what URL is it accessing? What headers that request had? Things like that.
So finally, the last concept, QTSS API Streams. Streams are kind of the most powerful way that modules can manipulate the client because they allow the module to send raw data directly back to the client. So if you want to send, say, a custom response to a QuickTime client, then you can just do that by writing to a stream. And there's a callback in the server called QTSS Write that allows you to communicate directly with the client just by sending it data.
The interesting thing is that the first demo that I showed you, the demo authorization module in that demo, didn't actually use RTSP streams. In order to allow or deny clients, all it really needs to do is use objects and call setValue in order to say that a request is allowed or denied. I've got a modified version of the demo authorization module.
Let me just bring down the server. So let me get this, the roles version of the demo authorization module out of here. And I'll get this new version with streams and put it into the modules folder. Restart the server. Okay, so now I'm going to go ahead and create a new version of the demo authorization Now the experience is going to be a little bit different when users are denied. So if I were to put in some kind of bad password here, instead of just getting re-prompted, I get redirected.
[Transcript missing]
OK, so what happened there? What the demo authorization module did, instead of just returning allowed or denied back to the client, it issued an RTSP redirect back to the client, which told the client to go and fetch this other movie, an error movie, and play that instead of just showing the prompt.
And RTSP redirects, in case you're not familiar, are kind of similar to, in the first session, we were talking a little bit about HTTP redirects. RTSP redirects work exactly the same way. It's just a way for the server to tell the client not to go to the URL that it's... So if the client sends a request to the server with a certain URL, the server can respond with a redirect telling the client to just go somewhere else. So the demo authorization module sent one of these redirects. And it's actually going to send a message to the client telling it to go and fetch that error movie. OK, back to slides.
OK, so-- and the thing is, is that the source, in order to do that, really isn't that much. There's just these two calls that I had to add. This is really the entire bit of code that I had to add to the demo authorization module in order to get that extra functionality in there.
So what did I do? I used QTSS API streams to send that RTSP redirect back to the client, because I needed to formulate an entire request, because a redirect is kind of a custom request, and send that back with the module communicating, sending raw data back to the client. So in order to do that, I got a stream ref out of the request object.
Streams are attributes in objects, so you first have to get the stream out of the object. And streams in different object types do different things. The stream that's contained in the RTSP request object is the stream that's contained in the RTSP request object, can be used to send data back to the client as an RTSP response.
So that's the first call there, that get value pointer, which returns a stream ref that can be used and passed into the bottom call there, the QTSS write call. And that's just a call which--it's just like any other stream interface, really, that you've seen. It just--you just write raw data to the stream, and it sends it back to the client.
So what the module is doing is that--sending that redirected buffer back to the client, and that's just a buffer in memory that contains the redirect response. So that's really all the code that I need to add in order to do that. So as I was saying before, there are a couple of different kinds of streams in the server. There's one contained in the QTSS session object, and again, that's a way to communicate directly to the RTSP user.
So the first one is the RTSP client sending RTSP responses. And then there's one also in the QTSS request object. Now, these do basically exactly the same thing. They're both ways to communicate back to the RTSP client, send RTSP responses. And the demo authorization module used the bottom one.
The only difference is that the top one, the RTSP session stream, doesn't buffer any data internally, and so you have to worry about the server. All of these streams are async because the server has to do everything async. We're managing lots and lots of client connections, so if you block, then you would be blocking lots of clients, not just one.
So if you use the session object stream, you have to worry about flow control, and that can be useful to use that stream, even though you need to worry about it because the bottom one buffers all data internally in order to protect the module from flow control, so it's kind of simpler.
But you want to be able to use that stream to do that. So that's the reason why I'm saying that the RTSP request object is a little bit more complex. You wouldn't want to send, like, a 30 megabyte file back using the RTSP request object because you'd be buffering that 30 megabytes in memory, which would not be good.
Okay, so there's two others in the API. There's a stream contained in the QTSS RTP stream object. It's a lot of streams in one sentence. But what that can do is if you write to that stream, you're writing media data back to the client over RTP. So, for instance, the Reflector Module that we have for reflecting live broadcasts and the hinted QuickTime Module, that uses RTP streams in the RTP stream object to send video and audio data back to the client.
So we have a very kind of universal interface for sending all kinds of different data back to the client. And then finally, the server also provides a stream ref for writing messages out to the error log, which is good for having modules give feedback back to the client. back to administrators.
Okay, so that's really coverage of all four concepts in QTSS API. Now, of course, like we're moving the server forward, we're also going to be moving the API forward. We're going to be continually adding features to it, and we're encouraging you as developers, if you do use the API, to give us feedback and tell us what you'd like us to do. And, you know, because it's open source, you can also go in there and become a contributor yourself. So here are just a couple of things that we are thinking about and working on.
We're moving our configuration file to XML, and one of the main reasons for that is just so that we can compartmentalize better preferences that have to do with specific modules. And as part of that effort, we're going to be providing individual QTSS API objects that represent individual modules. And so those module preferences will be stored in those module objects. And then finally... One of the big requests that we've had from the outside is to provide an API for the file system so that people can write modules to plug in custom file systems.
This is really important, for instance, if you want to have QTSS plug into a database or plug QTSS into a networked file system, some kind of custom file system. Now you can write a module, or at least whenever we finish this up, then you'll be able to write a module that can implement that file system and have QTSS generically start using your file system.
So those are just a couple of things that we're working on. And again, feedback is a big part of this process. So here are three key places to look for more information on QTSS and QTSS API. And a really nice thing about the API is that it's really well documented. We have a lot of documentation on it.
So hopefully... that'll also help ease the learning curve and all of the stuff that I talk about in this presentation is also available in that documentation. So in order to get that and to get the QTSS API SDK, you go to public source dot apple dot com, because it's an open source project, and then project streaming. Now if you're just interested in checking out QuickTime's streaming server, running on Mac OS X server, you can go to apple dot com, quicktime, servers dot html, you can download it. It's free if you've already got a copy of Mac OS X server, so it's really easy to get set up.
And if you go to the first link, actually, then we also have on that site binaries for all of our different platforms, except again Windows, and that's coming soon. So you can download there Linux binaries, you can download FreeBSD, Solaris, and we also have an open source version of Mac OS X server, I think.
And then finally, a really great resource for... talking to the QuickTime streaming server engineering team directly, and giving feedback and asking questions, is by using the Darwin streaming server development list. And the way that you get on that is lists dot apple dot com, streaming server, search for streaming server, and then it's really easy to sign on. And that's a really active list. Everyone's asking questions about their having problems compiling on certain platforms, or they have certain suggestions for the code.