ReaderWriterAVFoundation() { supportsExtension("mov","Quicktime movie format"); supportsExtension("mpg","Mpeg movie format"); supportsExtension("mp4","Mpeg movie format"); supportsExtension("m4v","Mpeg movie format"); supportsExtension("mpeg","Mpeg movie format"); supportsExtension("avfoundation","AVFoundation movie format"); supportsProtocol("http", "streaming media per http"); supportsProtocol("rtsp", "streaming media per rtsp"); }
void MediaRendererDevice::prepareForConnection(const ProtocolInfo& protocolInfo, ConnectionManager::ConnectionInfo& info) { if (info.direction != ConnectionManager::Direction::Input) { throw ConnectionManager::IncompatibleDirectionsException(); } if (!supportsProtocol(protocolInfo)) { throw ConnectionManager::IncompatibleProtocolException(); } // currently we only support one instance info.connectionId = 0; info.avTransportId = 0; info.renderingControlServiceId = 0; }
/** serializes the HTTP response status line plus headers into a byte-stream. * * This method is invoked right before the response content is written or the * response is flushed at all. * * It first sets the status code (if not done yet), invoked post_process callback, * performs connection-level response header modifications and then * builds the response chunk for status line and headers. * * Post-modification done <b>after</b> the post_process hook has been invoked: * <ol> * <li>set status code to 200 (Ok) if not set yet.</li> * <li>set Content-Type header to a default if not set yet.</li> * <li>set Connection header to keep-alive or close (computed value)</li> * <li>append Transfer-Encoding chunked if no Content-Length header is set.</li> * <li>optionally enable TCP_CORK if this is no keep-alive connection and the administrator allows it.</li> * </ol> * * \note this does not serialize the message body. */ Source* HttpRequest::serialize() { Buffer buffers; if (expectingContinue) status = HttpStatus::ExpectationFailed; else if (status == static_cast<HttpStatus>(0)) status = HttpStatus::Ok; if (!responseHeaders.contains("Content-Type")) { responseHeaders.push_back("Content-Type", "text/plain"); //!< \todo pass "default" content-type instead! } if (connection.worker().server().advertise() && !connection.worker().server().tag().empty()) { if (!responseHeaders.contains("Server")) { responseHeaders.push_back("Server", connection.worker().server().tag()); } else { responseHeaders.push_back("Via", connection.worker().server().tag()); } } // post-response hook connection.worker().server().onPostProcess(this); // setup (connection-level) response transfer if (supportsProtocol(1, 1) && !responseHeaders.contains("Content-Length") && !responseHeaders.contains("Transfer-Encoding") && !isResponseContentForbidden()) { responseHeaders.push_back("Transfer-Encoding", "chunked"); outputFilters.push_back(std::make_shared<ChunkedEncoder>()); } bool keepalive = connection.shouldKeepAlive(); if (!connection.worker().server().maxKeepAlive()) keepalive = false; // remaining request count, that is allowed on a persistent connection std::size_t rlim = connection.worker().server().maxKeepAliveRequests(); if (rlim) { rlim = connection.requestCount_ <= rlim ? rlim - connection.requestCount_ + 1 : 0; if (rlim == 0) // disable keep-alive, if max request count has been reached keepalive = false; } // only set Connection-response-header if found as request-header, too if (!requestHeader("Connection").empty() || keepalive != connection.shouldKeepAlive()) { if (keepalive) { responseHeaders.overwrite("Connection", "keep-alive"); if (rlim) { // sent keep-alive timeout and remaining request count char buf[80]; snprintf(buf, sizeof(buf), "timeout=%ld, max=%ld", static_cast<time_t>(connection.worker().server().maxKeepAlive().value()), rlim); responseHeaders.overwrite("Keep-Alive", buf); } else { // sent keep-alive timeout only (infinite request count) char buf[80]; snprintf(buf, sizeof(buf), "timeout=%ld", static_cast<time_t>(connection.worker().server().maxKeepAlive().value())); responseHeaders.overwrite("Keep-Alive", buf); } } else responseHeaders.overwrite("Connection", "close"); } connection.setShouldKeepAlive(keepalive); if (!connection.worker().server().tcpCork()) connection.socket()->setTcpCork(true); if (supportsProtocol(1, 1)) buffers.push_back("HTTP/1.1 "); else if (supportsProtocol(1, 0)) buffers.push_back("HTTP/1.0 "); else buffers.push_back("HTTP/0.9 "); buffers.push_back(statusCodes_[static_cast<int>(status)]); buffers.push_back(' '); buffers.push_back(statusStr(status)); buffers.push_back("\r\n"); for (auto& i: responseHeaders) { buffers.push_back(i.name.data(), i.name.size()); buffers.push_back(": "); buffers.push_back(i.value.data(), i.value.size()); buffers.push_back("\r\n"); }; buffers.push_back("\r\n"); return new BufferSource(std::move(buffers)); }