static int rtmp_probe(const char *url0, char *errbuf, size_t errlen, int timeout_ms) { RTMP *r; char *url = mystrdupa(url0); r = RTMP_Alloc(); RTMP_Init(r, NULL); if(!RTMP_SetupURL(r, url)) { snprintf(errbuf, errlen, "Unable to setup RTMP-session"); RTMP_Free(r); return BACKEND_PROBE_FAIL; } if(!RTMP_Connect(r, NULL, errbuf, errlen, timeout_ms)) { RTMP_Close(r); RTMP_Free(r); return BACKEND_PROBE_FAIL; } RTMP_SetReadTimeout(r, timeout_ms); if(!RTMP_ConnectStream(r, 0)) { snprintf(errbuf, errlen, "Unable to connect RTMP-stream"); RTMP_Close(r); RTMP_Free(r); return BACKEND_PROBE_FAIL; } RTMP_Close(r); RTMP_Free(r); return BACKEND_PROBE_OK; }
static gboolean gst_rtmp_sink_start (GstBaseSink * basesink) { GstRTMPSink *sink = GST_RTMP_SINK (basesink); if (!sink->uri) { GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, ("Please set URI for RTMP output"), ("No URI set before starting")); return FALSE; } sink->rtmp_uri = g_strdup (sink->uri); sink->rtmp = RTMP_Alloc (); RTMP_Init (sink->rtmp); if (!RTMP_SetupURL (sink->rtmp, sink->rtmp_uri)) { GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), ("Failed to setup URL '%s'", sink->uri)); RTMP_Free (sink->rtmp); sink->rtmp = NULL; g_free (sink->rtmp_uri); sink->rtmp_uri = NULL; return FALSE; } GST_DEBUG_OBJECT (sink, "Created RTMP object"); /* Mark this as an output connection */ RTMP_EnableWrite (sink->rtmp); sink->first = TRUE; return TRUE; }
/* * Class: net_butterflytv_rtmp_client_RtmpClient * Method: open * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_net_ossrs_sea_RtmpClient_open (JNIEnv * env, jobject thiz, jstring url_, jboolean isPublishMode) { const char *url = (*env)->GetStringUTFChars(env, url_, 0); rtmp = RTMP_Alloc(); if (rtmp == NULL) { return -1; } RTMP_Init(rtmp); int ret = RTMP_SetupURL(rtmp, url); if (!ret) { RTMP_Free(rtmp); return -2; } if (isPublishMode) { RTMP_EnableWrite(rtmp); } ret = RTMP_Connect(rtmp, NULL); if (!ret) { RTMP_Free(rtmp); return -3; } ret = RTMP_ConnectStream(rtmp, 0); if (!ret) { return -4; } (*env)->ReleaseStringUTFChars(env, url_, url); return 1; }
static event_t * rtmp_playvideo(const char *url0, media_pipe_t *mp, int flags, int priority, char *errbuf, size_t errlen, const char *mimetype) { rtmp_t r = {0}; event_t *e; char *url = mystrdupa(url0); prop_set_string(mp->mp_prop_type, "video"); RTMP_LogSetLevel(RTMP_LOGINFO); r.r = RTMP_Alloc(); RTMP_Init(r.r); if(!RTMP_SetupURL(r.r, url)) { snprintf(errbuf, errlen, "Unable to setup RTMP-session"); rtmp_free(&r); return NULL; } if(!RTMP_Connect(r.r, NULL)) { snprintf(errbuf, errlen, "Unable to connect RTMP-session"); rtmp_free(&r); return NULL; } if(!RTMP_ConnectStream(r.r, 0)) { snprintf(errbuf, errlen, "Unable to connect RTMP-stream"); rtmp_free(&r); return NULL; } mp->mp_audio.mq_stream = 0; mp->mp_video.mq_stream = 0; mp_configure(mp, MP_PLAY_CAPS_PAUSE, MP_BUFFER_DEEP); mp->mp_max_realtime_delay = (r.r->Link.timeout - 1) * 1000000; mp_become_primary(mp); e = rtmp_loop(&r, mp, url, errbuf, errlen); mp_flush(mp, 0); mp_shutdown(mp); TRACE(TRACE_DEBUG, "RTMP", "End of stream"); rtmp_free(&r); return e; }
int main(int argc, char **argv) { RTMP *rtmp=RTMP_Alloc(); if(!rtmp) return 1; RTMP_Init(rtmp); RTMP_Free(rtmp); return 0; }
/* open the file, do stuff necessary to go to PAUSED state */ static gboolean gst_rtmp_src_start (GstBaseSrc * basesrc) { GstRTMPSrc *src; src = GST_RTMP_SRC (basesrc); if (!src->uri) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No filename given")); return FALSE; } src->cur_offset = 0; src->last_timestamp = 0; src->discont = TRUE; src->rtmp = RTMP_Alloc (); if (!src->rtmp) { GST_ERROR_OBJECT (src, "Could not allocate librtmp's RTMP context"); goto error; } RTMP_Init (src->rtmp); if (!RTMP_SetupURL (src->rtmp, src->uri)) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to setup URL '%s'", src->uri)); goto error; } src->seekable = !(src->rtmp->Link.lFlags & RTMP_LF_LIVE); GST_INFO_OBJECT (src, "seekable %d", src->seekable); /* open if required */ if (!RTMP_IsConnected (src->rtmp)) { if (!RTMP_Connect (src->rtmp, NULL)) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Could not connect to RTMP stream \"%s\" for reading", src->uri)); goto error; } } return TRUE; error: if (src->rtmp) { RTMP_Free (src->rtmp); src->rtmp = NULL; } return FALSE; }
static CURLcode rtmp_setup_connection(struct connectdata *conn) { RTMP *r = RTMP_Alloc(); if(!r) return CURLE_OUT_OF_MEMORY; RTMP_Init(r); RTMP_SetBufferMS(r, DEF_BUFTIME); if(!RTMP_SetupURL(r, conn->data->change.url)) { RTMP_Free(r); return CURLE_URL_MALFORMAT; } conn->proto.generic = r; return CURLE_OK; }
Rtmp::Rtmp(QUrl url, QObject *parent) : QObject(parent) { m_rtmp = RTMP_Alloc(); RTMP_Init(m_rtmp); qDebug() << "Connecting to" << url; RTMP_SetupURL(m_rtmp, MY_URL ); RTMP_EnableWrite(m_rtmp); RTMP_Connect(m_rtmp, NULL); RTMP_ConnectStream(m_rtmp, 0); memset(&m_rtmpPacket, 0, sizeof(RTMPPacket)); qDebug() << RTMP_IsConnected(m_rtmp); }
/* open the file, do stuff necessary to go to PAUSED state */ static gboolean gst_rtmp_src_start (GstBaseSrc * basesrc) { GstRTMPSrc *src; gchar *uri_copy; src = GST_RTMP_SRC (basesrc); if (!src->uri) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No filename given")); return FALSE; } src->cur_offset = 0; src->last_timestamp = 0; src->seekable = TRUE; src->discont = TRUE; uri_copy = g_strdup (src->uri); src->rtmp = RTMP_Alloc (); RTMP_Init (src->rtmp); if (!RTMP_SetupURL (src->rtmp, uri_copy)) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Failed to setup URL '%s'", src->uri)); g_free (uri_copy); RTMP_Free (src->rtmp); src->rtmp = NULL; return FALSE; } /* open if required */ if (!RTMP_IsConnected (src->rtmp)) { if (!RTMP_Connect (src->rtmp, NULL)) { GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("Could not connect to RTMP stream \"%s\" for reading", src->uri)); RTMP_Free (src->rtmp); src->rtmp = NULL; return FALSE; } } return TRUE; }
LibRtmp::LibRtmp(bool isNeedLog, bool isNeedRecord) { if (isNeedLog) { flog_ = fopen("librtmp.log", "w"); RTMP_LogSetLevel(RTMP_LOGDEBUG2); RTMP_LogSetOutput(flog_); } else { flog_ = NULL; } rtmp_ = RTMP_Alloc(); RTMP_Init(rtmp_); RTMP_SetBufferMS(rtmp_, 300); streming_url_ = NULL; is_need_record_ = isNeedRecord; }
int RtmpSessionHandshake(RTMP_SESSION *pSession) { int iRet = 0; RTMPPacket *packet = (RTMPPacket *)malloc(sizeof(RTMPPacket)); if(NULL == packet) { return ERROR_FAILED; } RTMPPacket_Init(packet); pSession->pPkt = packet; RTMP *rtmp = RTMP_Alloc(); if(NULL == rtmp ) { return ERROR_FAILED; } RTMP_Init(rtmp); rtmp->m_sb.sb_socket = pSession->socket; pSession->prtmp = rtmp; pSession->state = RTMPSERVER_STATE_INIT; /* 进行握手处理 */ if(RTMP_Serve(rtmp)) { RTMPPacket_Free(pSession->pPkt); RTMPPacket_Init(pSession->pPkt); pSession->handshake = 1; pSession->arglen = 0; SetNonBlocking(pSession->socket); } else { iRet = -1; } return iRet; }
bool RTMPWriter::initialize() { if(!settings.url.size()) { printf("error: cannot initialize the RTMP Writer, no url set, call setURL() first.\n"); return false; } if(state == RW_STATE_INITIALIZED) { printf("error: already initialized.\n"); return false; } if(rtmp) { printf("error: already initialized a rtmp context, not creating another one!\n"); ::exit(EXIT_FAILURE); } rtmp = RTMP_Alloc(); if(!rtmp) { printf("error: cannot allocate the rtmp context.\n"); ::exit(EXIT_FAILURE); } RTMP_Init(rtmp); if(!RTMP_SetupURL(rtmp, (char*)settings.url.c_str())) { printf("error: cannot setup the url for the RTMP Writer.\n"); RTMP_Free(rtmp); rtmp = NULL; return false; } if(settings.username.size()) { rtmp->Link.pubUser.av_val = (char*)settings.username.c_str(); rtmp->Link.pubUser.av_len = settings.username.size(); } if(settings.password.size()) { rtmp->Link.pubPasswd.av_val = (char*)settings.password.c_str(); rtmp->Link.pubPasswd.av_len = settings.password.size(); } rtmp->Link.flashVer.av_val = (char*)"FMLE/3.0 (compatible; FMSc/1.0)"; // when streaming to a FMS you need this! rtmp->Link.flashVer.av_len = (int)strlen(rtmp->Link.flashVer.av_val); RTMP_EnableWrite(rtmp); if(!RTMP_Connect(rtmp, NULL)) { printf("error: cannot connect to the rtmp server: %s\n", settings.url.c_str()); RTMP_Free(rtmp); rtmp = NULL; /* if(state == RW_STATE_RECONNECTING) { state = RW_STATE_NONE; printf("@todo need to call the disconnect callback.\n"); //reconnect(); } */ return false; } if(!RTMP_ConnectStream(rtmp, 0)) { printf("error: cannot connect to the rtmp stream on %s.\n", settings.url.c_str()); RTMP_Free(rtmp); rtmp = NULL; if(state == RW_STATE_RECONNECTING) { state = RW_STATE_NONE; // reconnect(); } return false; } state = RW_STATE_INITIALIZED; return true; }
int main (int argc, char **argv) { char *url; int brate = 32; int c; while ((c = getopt(argc, argv, "u:b:")) != -1) switch (c) { case 'u': url = strdup(optarg); break; case 'b': brate = atoi(optarg); break; default: abort(); } // libev loop = ev_default_loop(0); ev_signal_init(&sigint_sig, sigint_cb, SIGINT); ev_signal_start (loop, &sigint_sig); ev_async_init(&async, send_cb); ev_async_start(loop, &async); // jack jack_status_t status; ringbuf = jack_ringbuffer_create(buffer_size); framebuf = malloc(buffer_samples * sizeof(jack_default_audio_sample_t)); client = jack_client_open("jack2rtmp", JackNullOption, &status); if (client == NULL) { fprintf(stderr, "jack server not running?\n"); return EXIT_FAILURE; } jack_on_shutdown(client, jack_shutdown, NULL); jack_set_process_callback(client, jack_callback, NULL); //jack_set_latency_callback(client, jack_latency_callback, NULL); output_port = jack_port_register(client, "1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); //jack_port_register(client, "2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (jack_activate(client)) { fprintf(stderr, "cannot activate client"); } // lame mp3 = lame_init(); lame_set_num_channels(mp3, 1); lame_set_mode(mp3, MONO); lame_set_in_samplerate(mp3, 48000); lame_set_out_samplerate(mp3, 44100); lame_set_quality(mp3, 2); // 0=best (very slow), 9=worst. lame_set_brate(mp3, brate); lame_init_params(mp3); // rtmp rtmp_o = RTMP_Alloc(); if (rtmp_o == NULL) { fprintf(stderr, "RTMP_Alloc\n"); return EXIT_FAILURE; } RTMP_Init(rtmp_o); RTMP_SetupURL(rtmp_o, url); RTMP_EnableWrite(rtmp_o); if (!RTMP_Connect(rtmp_o, NULL) || !RTMP_ConnectStream(rtmp_o, 0)) { RTMP_Free(rtmp_o); fprintf(stderr, "Can not connect.\n"); return EXIT_FAILURE; } else { fprintf(stderr, "Connected.\n"); } /* char *rtmp_buffer = malloc(4096); char *rtmp_top = rtmp_buffer + RTMP_MAX_HEADER_SIZE; char *outend = rtmp_buffer + 4096; *rtmp_top = (uint8_t) AMF_STRING; rtmp_top++; rtmp_top = put_amf_string(rtmp_top, "@setDataFrame"); *rtmp_top = (uint8_t) AMF_STRING; rtmp_top++; rtmp_top = put_amf_string(rtmp_top, "onMetaData"); // описание объекта *rtmp_top = (uint8_t) 8; rtmp_top++; rtmp_top = AMF_EncodeInt32(rtmp_top, outend, 8); // содержимое объекта rtmp_top = put_amf_string(rtmp_top, "duration"); rtmp_top = AMF_EncodeNumber(rtmp_top, outend, 0); rtmp_top = put_amf_string(rtmp_top, "audiodatarate"); rtmp_top = AMF_EncodeNumber(rtmp_top, outend, brate); rtmp_top = put_amf_string(rtmp_top, "audiosamplerate"); rtmp_top = AMF_EncodeNumber(rtmp_top, outend, 44100); rtmp_top = put_amf_string(rtmp_top, "audiosamplesize"); rtmp_top = AMF_EncodeNumber(rtmp_top, outend, 16); rtmp_top = put_amf_string(rtmp_top, "stereo"); rtmp_top = AMF_EncodeBoolean(rtmp_top, outend, FALSE); rtmp_top = put_amf_string(rtmp_top, "audiocodecid"); rtmp_top = AMF_EncodeNumber(rtmp_top, outend, 2); rtmp_top = put_amf_string(rtmp_top, "encoder"); *rtmp_top = (uint8_t) AMF_STRING; rtmp_top++; rtmp_top = put_amf_string(rtmp_top, "Lavf53.21.1"); rtmp_top = put_amf_string(rtmp_top, "filesize"); rtmp_top = AMF_EncodeNumber(rtmp_top, outend, 0); // конец объекта rtmp_top = put_amf_string(rtmp_top, ""); *rtmp_top = (uint8_t) AMF_OBJECT_END; rtmp_top++; rtmp_w.m_headerType = RTMP_PACKET_SIZE_LARGE; rtmp_w.m_nChannel = 0x04; // source channel rtmp_w.m_nBodySize = rtmp_top - rtmp_buffer - RTMP_MAX_HEADER_SIZE; rtmp_w.m_packetType = RTMP_PACKET_TYPE_INFO; rtmp_w.m_nInfoField2 = rtmp_o->m_stream_id; rtmp_w.m_body = rtmp_buffer + RTMP_MAX_HEADER_SIZE; if ( !RTMP_SendPacket(rtmp_o, &rtmp_w, TRUE) ) { fprintf(stderr, "RTMP_SendPacket error\n"); } free(rtmp_buffer); */ int off = 0; setsockopt(RTMP_Socket(rtmp_o), SOL_TCP, TCP_NODELAY, &off, sizeof(off)); rtmp_i = TRUE; ev_loop(loop, 0); jack_ringbuffer_free(ringbuf); //jack_client_close(client); return EXIT_SUCCESS; }
DWORD WINAPI RTMPPublisher::CreateConnectionThread(RTMPPublisher *publisher) { //------------------------------------------------------ // set up URL bool bRetry = false; bool bSuccess = false; bool bCanRetry = false; String failReason; String strBindIP; int serviceID = AppConfig->GetInt (TEXT("Publish"), TEXT("Service")); String strURL = AppConfig->GetString(TEXT("Publish"), TEXT("URL")); String strPlayPath = AppConfig->GetString(TEXT("Publish"), TEXT("PlayPath")); strURL.KillSpaces(); strPlayPath.KillSpaces(); LPSTR lpAnsiURL = NULL, lpAnsiPlaypath = NULL; RTMP *rtmp = NULL; //-------------------------------- // unbelievably disgusting hack for elgato devices String strOldDirectory; UINT dirSize = GetCurrentDirectory(0, 0); strOldDirectory.SetLength(dirSize); GetCurrentDirectory(dirSize, strOldDirectory.Array()); OSSetCurrentDirectory(API->GetAppPath()); //-------------------------------- if(!strURL.IsValid()) { failReason = TEXT("No server specified to connect to"); goto end; } if(serviceID != 0) { XConfig serverData; if(!serverData.Open(TEXT("services.xconfig"))) { failReason = TEXT("Could not open services.xconfig"); goto end; } XElement *services = serverData.GetElement(TEXT("services")); if(!services) { failReason = TEXT("Could not find any services in services.xconfig"); goto end; } XElement *service = NULL; DWORD numServices = services->NumElements(); for(UINT i=0; i<numServices; i++) { XElement *curService = services->GetElementByID(i); if(curService->GetInt(TEXT("id")) == serviceID) { service = curService; break; } } if(!service) { failReason = TEXT("Could not find the service specified in services.xconfig"); goto end; } XElement *servers = service->GetElement(TEXT("servers")); if(!servers) { failReason = TEXT("Could not find any servers for the service specified in services.xconfig"); goto end; } XDataItem *item = servers->GetDataItem(strURL); if(!item) item = servers->GetDataItemByID(0); strURL = item->GetData(); Log(TEXT("Using RTMP service: %s"), service->GetName()); Log(TEXT(" Server selection: %s"), strURL.Array()); } //------------------------------------------------------ // now back to the elgato directory if it needs the directory changed still to function *sigh* OSSetCurrentDirectory(strOldDirectory); //------------------------------------------------------ rtmp = RTMP_Alloc(); RTMP_Init(rtmp); RTMP_LogSetCallback(librtmpErrorCallback); //RTMP_LogSetLevel(RTMP_LOGERROR); lpAnsiURL = strURL.CreateUTF8String(); lpAnsiPlaypath = strPlayPath.CreateUTF8String(); if(!RTMP_SetupURL2(rtmp, lpAnsiURL, lpAnsiPlaypath)) { failReason = Str("Connection.CouldNotParseURL"); goto end; } char *rtmpUser = AppConfig->GetString(TEXT("Publish"), TEXT("Username")).CreateUTF8String(); char *rtmpPass = AppConfig->GetString(TEXT("Publish"), TEXT("Password")).CreateUTF8String(); if (rtmpUser) { rtmp->Link.pubUser.av_val = rtmpUser; rtmp->Link.pubUser.av_len = (int)strlen(rtmpUser); } if (rtmpPass) { rtmp->Link.pubPasswd.av_val = rtmpPass; rtmp->Link.pubPasswd.av_len = (int)strlen(rtmpPass); } RTMP_EnableWrite(rtmp); //set it to publish rtmp->Link.swfUrl.av_len = rtmp->Link.tcUrl.av_len; rtmp->Link.swfUrl.av_val = rtmp->Link.tcUrl.av_val; /*rtmp->Link.pageUrl.av_len = rtmp->Link.tcUrl.av_len; rtmp->Link.pageUrl.av_val = rtmp->Link.tcUrl.av_val;*/ rtmp->Link.flashVer.av_val = "FMLE/3.0 (compatible; FMSc/1.0)"; rtmp->Link.flashVer.av_len = (int)strlen(rtmp->Link.flashVer.av_val); //----------------------------------------- UINT tcpBufferSize = AppConfig->GetInt(TEXT("Publish"), TEXT("TCPBufferSize"), 64*1024); if(tcpBufferSize < 8192) tcpBufferSize = 8192; else if(tcpBufferSize > 1024*1024) tcpBufferSize = 1024*1024; rtmp->m_outChunkSize = 4096;//RTMP_DEFAULT_CHUNKSIZE;// rtmp->m_bSendChunkSizeInfo = TRUE; rtmp->m_bUseNagle = TRUE; strBindIP = AppConfig->GetString(TEXT("Publish"), TEXT("BindToIP"), TEXT("Default")); if (scmp(strBindIP, TEXT("Default"))) { rtmp->m_bindIP.addr.sin_family = AF_INET; rtmp->m_bindIP.addrLen = sizeof(rtmp->m_bindIP.addr); if (WSAStringToAddress(strBindIP.Array(), AF_INET, NULL, (LPSOCKADDR)&rtmp->m_bindIP.addr, &rtmp->m_bindIP.addrLen) == SOCKET_ERROR) { // no localization since this should rarely/never happen failReason = TEXT("WSAStringToAddress: Could not parse address"); goto end; } } LogInterfaceType(rtmp); //----------------------------------------- if(!RTMP_Connect(rtmp, NULL)) { failReason = Str("Connection.CouldNotConnect"); failReason << TEXT("\r\n\r\n") << RTMPPublisher::GetRTMPErrors(); bCanRetry = true; goto end; } if(!RTMP_ConnectStream(rtmp, 0)) { failReason = Str("Connection.InvalidStream"); failReason << TEXT("\r\n\r\n") << RTMPPublisher::GetRTMPErrors(); bCanRetry = true; goto end; } //----------------------------------------- OSDebugOut(TEXT("Connected: %u\r\n"), OSGetTime()); publisher->RequestKeyframe(1000); //----------------------------------------- bSuccess = true; end: if (lpAnsiURL) Free(lpAnsiURL); if (lpAnsiPlaypath) Free(lpAnsiPlaypath); if(!bSuccess) { if(rtmp) { RTMP_Close(rtmp); RTMP_Free(rtmp); } if(failReason.IsValid()) App->SetStreamReport(failReason); if(!publisher->bStopping) PostMessage(hwndMain, OBS_REQUESTSTOP, bCanRetry ? 0 : 1, 0); Log(TEXT("Connection to %s failed: %s"), strURL.Array(), failReason.Array()); publisher->bStopping = true; } else { publisher->Init(rtmp, tcpBufferSize); publisher->bConnected = true; publisher->bConnecting = false; } return 0; }
static event_t * rtmp_playvideo(const char *url0, media_pipe_t *mp, int flags, int priority, char *errbuf, size_t errlen, const char *mimetype, const char *canonical_url) { rtmp_t r = {0}; event_t *e; char *url = mystrdupa(url0); prop_set_string(mp->mp_prop_type, "video"); RTMP_LogSetLevel(RTMP_LOGINFO); r.r = RTMP_Alloc(); RTMP_Init(r.r); int64_t start = video_get_restartpos(canonical_url); if(!RTMP_SetupURL(r.r, url)) { snprintf(errbuf, errlen, "Unable to setup RTMP-session"); rtmp_free(&r); return NULL; } if(!RTMP_Connect(r.r, NULL)) { snprintf(errbuf, errlen, "Unable to connect RTMP-session"); rtmp_free(&r); return NULL; } if(!RTMP_ConnectStream(r.r, start)) { snprintf(errbuf, errlen, "Unable to connect RTMP-stream"); rtmp_free(&r); return NULL; } r.seek_origin = start; r.mp = mp; r.hold = 0; r.lost_focus = 0; r.epoch = 1; mp->mp_audio.mq_stream = 0; mp->mp_video.mq_stream = 0; if(start > 0) { r.seekpos = start * 1000; r.seekbase = r.seekpos; mp->mp_video.mq_seektarget = r.seekpos; mp->mp_audio.mq_seektarget = r.seekpos; } else { mp->mp_video.mq_seektarget = AV_NOPTS_VALUE; mp->mp_audio.mq_seektarget = AV_NOPTS_VALUE; r.seekbase = AV_NOPTS_VALUE; r.seekpos = AV_NOPTS_VALUE; } mp_configure(mp, MP_PLAY_CAPS_PAUSE, MP_BUFFER_DEEP); mp->mp_max_realtime_delay = (r.r->Link.timeout - 1) * 1000000; mp_become_primary(mp); metadb_register_play(canonical_url, 0, CONTENT_VIDEO); r.canonical_url = canonical_url; r.restartpos_last = -1; e = rtmp_loop(&r, mp, url, errbuf, errlen); if(r.total_duration) { int p = r.seekbase / (r.total_duration * 10); if(p >= video_settings.played_threshold) { TRACE(TRACE_DEBUG, "RTMP", "Playback reached %d%%, counting as played", p); metadb_register_play(canonical_url, 1, CONTENT_VIDEO); metadb_set_video_restartpos(canonical_url, -1); } } mp_flush(mp, 0); mp_shutdown(mp); TRACE(TRACE_DEBUG, "RTMP", "End of stream"); rtmp_free(&r); return e; }
static event_t * rtmp_playvideo(const char *url0, media_pipe_t *mp, char *errbuf, size_t errlen, video_queue_t *vq, struct vsource_list *vsl, const video_args_t *va0) { video_args_t va = *va0; rtmp_t r = {0}; event_t *e; char *url = mystrdupa(url0); mp_set_url(mp, va0->canonical_url, va0->parent_url, va0->parent_title); usage_event("Play video", 1, USAGE_SEG("format", "RTMP")); prop_set(mp->mp_prop_metadata, "format", PROP_SET_STRING, "RTMP"); prop_set(mp->mp_prop_root, "loading", PROP_SET_INT, 1); va.flags |= BACKEND_VIDEO_NO_FS_SCAN; rtmp_log_level = RTMP_LOGINFO; RTMP_LogSetLevel(rtmp_log_level); r.r = RTMP_Alloc(); RTMP_Init(r.r, mp->mp_cancellable); int64_t start = playinfo_get_restartpos(va.canonical_url, va.title, va.resume_mode); if(!RTMP_SetupURL(r.r, url)) { snprintf(errbuf, errlen, "Unable to setup RTMP-session"); rtmp_free(&r); return NULL; } r.r->Link.lFlags |= RTMP_LF_SWFV; if(!RTMP_Connect(r.r, NULL, errbuf, errlen, 5000)) { rtmp_free(&r); return NULL; } if(!RTMP_ConnectStream(r.r, 0)) { snprintf(errbuf, errlen, "Unable to connect RTMP-stream"); rtmp_free(&r); return NULL; } if(start) RTMP_SendSeek(r.r, start); r.mp = mp; mp->mp_audio.mq_stream = 0; mp->mp_video.mq_stream = 0; if(start > 0) { r.seekpos_video = start * 1000; r.seekpos_audio = start * 1000; mp->mp_seek_base = r.seekpos_video; mp->mp_video.mq_seektarget = r.seekpos_video; mp->mp_audio.mq_seektarget = r.seekpos_video; } else { mp->mp_video.mq_seektarget = AV_NOPTS_VALUE; mp->mp_audio.mq_seektarget = AV_NOPTS_VALUE; mp->mp_seek_base = 0; r.seekpos_audio = AV_NOPTS_VALUE; r.seekpos_video = AV_NOPTS_VALUE; } mp_configure(mp, MP_CAN_PAUSE, MP_BUFFER_DEEP, 0, "video"); mp->mp_max_realtime_delay = (r.r->Link.timeout - 1) * 1000000; mp_become_primary(mp); playinfo_register_play(va.canonical_url, 0); r.canonical_url = va.canonical_url; r.restartpos_last = -1; r.url = url; r.va = &va; r.is_loading = 1; e = rtmp_loop(&r, mp, url, errbuf, errlen); if(r.ss) sub_scanner_destroy(r.ss); if(r.total_duration) { int p = mp->mp_seek_base / (r.total_duration * 10); if(p >= video_settings.played_threshold) { TRACE(TRACE_DEBUG, "RTMP", "Playback reached %d%%, counting as played", p); playinfo_register_play(va.canonical_url, 1); playinfo_set_restartpos(va.canonical_url, -1, 0); } else { playinfo_set_restartpos(va.canonical_url, mp->mp_seek_base / 1000, 0); } } mp_shutdown(mp); TRACE(TRACE_DEBUG, "RTMP", "End of playback"); rtmp_free(&r); return e; }
int main(int argc, char *argv[]) { struct stat sb; int opt, i; int chapter = 0, available = 0; char *book = NULL; char audio[256]; while ((opt = getopt(argc, argv, "v:a:b:c:l")) != -1) { switch (opt) { case 'v': version = optarg; break; case 'a': author = optarg; break; case 'b': book = optarg; break; case 'c': chapter = atoi(optarg); break; case 'l': return list(); } } sprintf(audio, "%s-%s", version, author); for (i = 0; i < ARRAY_SIZE(audios); i++) { if (strcasecmp(audios[i].audio, audio) == 0) { available = 1; break; } } if (!available) { fprintf(stderr, "Invalid version `%s' or author `%s'\n", version, author); return EINVAL; } for (i = 0; i < ARRAY_SIZE(books); i++) { if (!book || strcasecmp(books[i].osis, book) == 0) { available = 1; break; } } if (!available) { fprintf(stderr, "Invalid book `%s'\n", book); return EINVAL; } if ((rtmp = RTMP_Alloc()) == NULL || (buffer = malloc(BUFSIZ)) == NULL) { perror("malloc"); return ENOMEM; } if (stat(audio, &sb) == -1) { if (errno == ENOENT) { mkdir(audio, 0755); } else { perror("stat"); return errno; } } else if (!S_ISDIR(sb.st_mode)) { fprintf(stderr, "%s is not a directory\n", audio); return errno; } if (book) { if (chapter > books[i].chapter) { fprintf(stderr, "Invalid chapter `%d'\n", chapter); return EINVAL; } if (chapter) { download(books[i].osis, chapter); } else { for (chapter = 1; chapter <= books[i].chapter; chapter++) { download(books[i].osis, chapter); } } } else { for (i = 0; i < ARRAY_SIZE(books); i++) { for (chapter = 1; chapter <= books[i].chapter; chapter++) { download(books[i].osis, chapter); } } } RTMP_Free(rtmp); free(buffer); return 0; }
//Publish using RTMP_SendPacket() int publish_using_packet(){ RTMP *rtmp=NULL; RTMPPacket *packet=NULL; uint32_t start_time=0; uint32_t now_time=0; //the timestamp of the previous frame long pre_frame_time=0; long lasttime=0; int bNextIsKey=1; uint32_t preTagsize=0; //packet attributes uint32_t type=0; uint32_t datalength=0; uint32_t timestamp=0; uint32_t streamid=0; FILE*fp=NULL; fp=fopen("../live.flv","rb"); if (!fp){ RTMP_LogPrintf("Open File Error.\n"); // CleanupSockets(); return -1; } /* set log level */ //RTMP_LogLevel loglvl=RTMP_LOGDEBUG; //RTMP_LogSetLevel(loglvl); // if (!InitSockets()){ // RTMP_LogPrintf("Init Socket Err\n"); // return -1; // } rtmp=RTMP_Alloc(); RTMP_Init(rtmp); //set connection timeout,default 30s rtmp->Link.timeout=5; if(!RTMP_SetupURL(rtmp,"rtmp://101.251.251.93:1935/myapp/mystream")) { RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n"); RTMP_Free(rtmp); // CleanupSockets(); return -1; } //if unable,the AMF command would be 'play' instead of 'publish' RTMP_EnableWrite(rtmp); if (!RTMP_Connect(rtmp,NULL)){ RTMP_Log(RTMP_LOGERROR,"Connect Err\n"); RTMP_Free(rtmp); // CleanupSockets(); return -1; } if (!RTMP_ConnectStream(rtmp,0)){ RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n"); RTMP_Close(rtmp); RTMP_Free(rtmp); // CleanupSockets(); return -1; } packet=(RTMPPacket*)malloc(sizeof(RTMPPacket)); RTMPPacket_Alloc(packet,1024*64); RTMPPacket_Reset(packet); packet->m_hasAbsTimestamp = 0; packet->m_nChannel = 0x04; packet->m_nInfoField2 = rtmp->m_stream_id; RTMP_LogPrintf("Start to send data ...\n"); //jump over FLV Header fseek(fp,9,SEEK_SET); //jump over previousTagSizen fseek(fp,4,SEEK_CUR); start_time=RTMP_GetTime(); while(1) { if((((now_time=RTMP_GetTime())-start_time) <(pre_frame_time)) && bNextIsKey){ //wait for 1 sec if the send process is too fast //this mechanism is not very good,need some improvement if(pre_frame_time>lasttime){ RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time); lasttime=pre_frame_time; } sleep(1); continue; } //not quite the same as FLV spec if(!ReadU8(&type,fp)) break; if(!ReadU24(&datalength,fp)) break; if(!ReadTime(×tamp,fp)) break; if(!ReadU24(&streamid,fp)) break; if (type!=0x08&&type!=0x09){ //jump over non_audio and non_video frame, //jump over next previousTagSizen at the same time fseek(fp,datalength+4,SEEK_CUR); continue; } if(fread(packet->m_body,1,datalength,fp)!=datalength) break; packet->m_headerType = RTMP_PACKET_SIZE_LARGE; packet->m_nTimeStamp = timestamp; packet->m_packetType = type; packet->m_nBodySize = datalength; pre_frame_time=timestamp; if (!RTMP_IsConnected(rtmp)){ RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n"); break; } if (!RTMP_SendPacket(rtmp,packet,0)){ RTMP_Log(RTMP_LOGERROR,"Send Error\n"); break; } if(!ReadU32(&preTagsize,fp)) break; if(!PeekU8(&type,fp)) break; if(type==0x09){ if(fseek(fp,11,SEEK_CUR)!=0) break; if(!PeekU8(&type,fp)){ break; } if(type==0x17) bNextIsKey=1; else bNextIsKey=0; fseek(fp,-11,SEEK_CUR); } } RTMP_LogPrintf("\nSend Data Over\n"); if(fp) fclose(fp); if (rtmp!=NULL){ RTMP_Close(rtmp); RTMP_Free(rtmp); rtmp=NULL; } if (packet!=NULL){ RTMPPacket_Free(packet); free(packet); packet=NULL; } // CleanupSockets(); return 0; }
//Publish using RTMP_Write() int publish_using_write(){ uint32_t start_time=0; uint32_t now_time=0; uint32_t pre_frame_time=0; uint32_t lasttime=0; int bNextIsKey=0; char* pFileBuf=NULL; //read from tag header uint32_t type=0; uint32_t datalength=0; uint32_t timestamp=0; RTMP *rtmp=NULL; FILE*fp=NULL; fp=fopen("cuc_ieschool.flv","rb"); if (!fp){ RTMP_LogPrintf("Open File Error.\n"); // CleanupSockets(); return -1; } /* set log level */ //RTMP_LogLevel loglvl=RTMP_LOGDEBUG; //RTMP_LogSetLevel(loglvl); // if (!InitSockets()){ // RTMP_LogPrintf("Init Socket Err\n"); // return -1; // } rtmp=RTMP_Alloc(); RTMP_Init(rtmp); //set connection timeout,default 30s rtmp->Link.timeout=5; if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream")) { RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n"); RTMP_Free(rtmp); // CleanupSockets(); return -1; } RTMP_EnableWrite(rtmp); //1hour RTMP_SetBufferMS(rtmp, 3600*1000); if (!RTMP_Connect(rtmp,NULL)){ RTMP_Log(RTMP_LOGERROR,"Connect Err\n"); RTMP_Free(rtmp); // CleanupSockets(); return -1; } if (!RTMP_ConnectStream(rtmp,0)){ RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n"); RTMP_Close(rtmp); RTMP_Free(rtmp); //CleanupSockets(); return -1; } printf("Start to send data ...\n"); //jump over FLV Header fseek(fp,9,SEEK_SET); //jump over previousTagSizen fseek(fp,4,SEEK_CUR); start_time=RTMP_GetTime(); while(1) { if((((now_time=RTMP_GetTime())-start_time) <(pre_frame_time)) && bNextIsKey){ //wait for 1 sec if the send process is too fast //this mechanism is not very good,need some improvement if(pre_frame_time>lasttime){ RTMP_LogPrintf("TimeStamp:%8lu ms\n", pre_frame_time); lasttime=pre_frame_time; } sleep(1); continue; } //jump over type fseek(fp,1,SEEK_CUR); if(!ReadU24(&datalength,fp)) break; if(!ReadTime(×tamp,fp)) break; //jump back fseek(fp,-8,SEEK_CUR); pFileBuf=(char*)malloc(11+datalength+4); memset(pFileBuf,0,11+datalength+4); if(fread(pFileBuf,1,11+datalength+4,fp)!=(11+datalength+4)) break; pre_frame_time=timestamp; if (!RTMP_IsConnected(rtmp)){ RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n"); break; } if (!RTMP_Write(rtmp,pFileBuf,11+datalength+4)){ RTMP_Log(RTMP_LOGERROR,"Rtmp Write Error\n"); break; } free(pFileBuf); pFileBuf=NULL; if(!PeekU8(&type,fp)) break; if(type==0x09){ if(fseek(fp,11,SEEK_CUR)!=0) break; if(!PeekU8(&type,fp)){ break; } if(type==0x17) bNextIsKey=1; else bNextIsKey=0; fseek(fp,-11,SEEK_CUR); } } RTMP_LogPrintf("\nSend Data Over\n"); if(fp) fclose(fp); if (rtmp!=NULL){ RTMP_Close(rtmp); RTMP_Free(rtmp); rtmp=NULL; } if(pFileBuf){ free(pFileBuf); pFileBuf=NULL; } //CleanupSockets(); return 0; }
int main(int argc, char* argv[]) { InitSockets(); double duration = -1; int nRead; //is live stream ? bool bLiveStream = TRUE; int bufsize = 1024 * 1024 * 10; char *buf = (char*)malloc(bufsize); memset(buf, 0, bufsize); long countbufsize = 0; FILE *fp = fopen("receive.flv", "wb"); if (!fp) { RTMP_LogPrintf("Open File Error.\n"); CleanupSockets(); return -1; } /* set log level */ RTMP_LogLevel loglvl = RTMP_LOGDEBUG; RTMP_LogSetLevel(loglvl); RTMP *rtmp = RTMP_Alloc(); RTMP_Init(rtmp); //set connection timeout,default 30s rtmp->Link.timeout = 10; char* rtmpFilePath = "d:\\rtmp.raw"; rtmp->m_pRTMPFile = fopen(rtmpFilePath,"rb"); if (!rtmp->m_pRTMPFile) { RTMP_LogPrintf("Failed to open File :%s\n", rtmpFilePath); return FALSE; } // HKS's live URL if(!RTMP_SetupURL(rtmp, "rtmp://live.hkstv.hk.lxdns.com/live/hks")) { RTMP_Log(RTMP_LOGERROR, "SetupURL Err\n"); RTMP_Free(rtmp); CleanupSockets(); return -1; } if (bLiveStream) { rtmp->Link.lFlags |= RTMP_LF_LIVE; } //1hour RTMP_SetBufferMS(rtmp, 3600 * 1000); if(!RTMP_Connect(rtmp, NULL)) { RTMP_Log(RTMP_LOGERROR, "Connect Err\n"); RTMP_Free(rtmp); CleanupSockets(); return -1; } if(!RTMP_ConnectStream(rtmp, 0)) { RTMP_Log(RTMP_LOGERROR, "ConnectStream Err\n"); RTMP_Close(rtmp); RTMP_Free(rtmp); CleanupSockets(); return -1; } while(nRead = RTMP_Read(rtmp, buf, bufsize)) { fwrite(buf, 1, nRead, fp); countbufsize += nRead; RTMP_LogPrintf("Receive: %5dByte, Total: %5.2fkB\n", nRead, countbufsize * 1.0 / 1024); } if(fp) fclose(fp); if(fpPcap) fclose(fpPcap); if (rtmp->m_pRTMPFile) { fclose(rtmp->m_pRTMPFile); } if(buf) { free(buf); } if(rtmp) { RTMP_Close(rtmp); RTMP_Free(rtmp); CleanupSockets(); rtmp = NULL; } return 0; }
static event_t * rtmp_playvideo(const char *url0, media_pipe_t *mp, char *errbuf, size_t errlen, video_queue_t *vq, struct vsource_list *vsl, const video_args_t *va0) { video_args_t va = *va0; rtmp_t r = {0}; event_t *e; char *url = mystrdupa(url0); va.flags |= BACKEND_VIDEO_NO_FS_SCAN; prop_set_string(mp->mp_prop_type, "video"); rtmp_log_level = RTMP_LOGINFO; RTMP_LogSetLevel(rtmp_log_level); r.r = RTMP_Alloc(); RTMP_Init(r.r); int64_t start = 0; if(va.flags & BACKEND_VIDEO_RESUME || (video_settings.resume_mode == VIDEO_RESUME_YES && !(va.flags & BACKEND_VIDEO_START_FROM_BEGINNING))) start = video_get_restartpos(va.canonical_url); if(!RTMP_SetupURL(r.r, url)) { snprintf(errbuf, errlen, "Unable to setup RTMP-session"); rtmp_free(&r); return NULL; } r.r->Link.lFlags |= RTMP_LF_SWFV; if(!RTMP_Connect(r.r, NULL)) { snprintf(errbuf, errlen, "Unable to connect RTMP-session"); rtmp_free(&r); return NULL; } if(!RTMP_ConnectStream(r.r, 0)) { snprintf(errbuf, errlen, "Unable to connect RTMP-stream"); rtmp_free(&r); return NULL; } if(start) RTMP_SendSeek(r.r, start); r.mp = mp; mp->mp_audio.mq_stream = 0; mp->mp_video.mq_stream = 0; if(start > 0) { r.seekpos_video = start * 1000; r.seekpos_audio = start * 1000; mp->mp_seek_base = r.seekpos_video; mp->mp_video.mq_seektarget = r.seekpos_video; mp->mp_audio.mq_seektarget = r.seekpos_video; } else { mp->mp_video.mq_seektarget = AV_NOPTS_VALUE; mp->mp_audio.mq_seektarget = AV_NOPTS_VALUE; mp->mp_seek_base = 0; r.seekpos_audio = AV_NOPTS_VALUE; r.seekpos_video = AV_NOPTS_VALUE; } mp_configure(mp, MP_PLAY_CAPS_PAUSE, MP_BUFFER_DEEP, 0); mp->mp_max_realtime_delay = (r.r->Link.timeout - 1) * 1000000; mp_become_primary(mp); metadb_register_play(va.canonical_url, 0, CONTENT_VIDEO); r.canonical_url = va.canonical_url; r.restartpos_last = -1; sub_scanner_t *ss = sub_scanner_create(url, mp->mp_prop_subtitle_tracks, &va, 0); e = rtmp_loop(&r, mp, url, errbuf, errlen); sub_scanner_destroy(ss); if(r.total_duration) { int p = mp->mp_seek_base / (r.total_duration * 10); if(p >= video_settings.played_threshold) { TRACE(TRACE_DEBUG, "RTMP", "Playback reached %d%%, counting as played", p); metadb_register_play(va.canonical_url, 1, CONTENT_VIDEO); metadb_set_video_restartpos(va.canonical_url, -1); } } mp_flush(mp, 0); mp_shutdown(mp); TRACE(TRACE_DEBUG, "RTMP", "End of stream"); rtmp_free(&r); return e; }
void doServe(STREAMING_SERVER * server, // server socket and state (our listening socket) int sockfd // client connection socket ) { server->state = STREAMING_IN_PROGRESS; RTMP *rtmp = RTMP_Alloc(); /* our session with the real client */ RTMPPacket packet = { 0 }; // timeout for http requests fd_set fds; struct timeval tv; memset(&tv, 0, sizeof(struct timeval)); tv.tv_sec = 5; FD_ZERO(&fds); FD_SET(sockfd, &fds); if (select(sockfd + 1, &fds, NULL, NULL, &tv) <= 0) { RTMP_Log(RTMP_LOGERROR, "Request timeout/select failed, ignoring request"); goto quit; } else { RTMP_Init(rtmp); rtmp->m_sb.sb_socket = sockfd; if (sslCtx && !RTMP_TLS_Accept(rtmp, sslCtx)) { RTMP_Log(RTMP_LOGERROR, "TLS handshake failed"); goto cleanup; } if (!RTMP_Serve(rtmp)) { RTMP_Log(RTMP_LOGERROR, "Handshake failed"); goto cleanup; } } server->arglen = 0; while (RTMP_IsConnected(rtmp) && RTMP_ReadPacket(rtmp, &packet)) { if (!RTMPPacket_IsReady(&packet)) continue; ServePacket(server, rtmp, &packet); RTMPPacket_Free(&packet); } cleanup: RTMP_LogPrintf("Closing connection... "); RTMP_Close(rtmp); /* Should probably be done by RTMP_Close() ... */ rtmp->Link.playpath.av_val = NULL; rtmp->Link.tcUrl.av_val = NULL; rtmp->Link.swfUrl.av_val = NULL; rtmp->Link.pageUrl.av_val = NULL; rtmp->Link.app.av_val = NULL; rtmp->Link.flashVer.av_val = NULL; if (rtmp->Link.usherToken.av_val) { free(rtmp->Link.usherToken.av_val); rtmp->Link.usherToken.av_val = NULL; } RTMP_Free(rtmp); RTMP_LogPrintf("done!\n\n"); quit: if (server->state == STREAMING_IN_PROGRESS) server->state = STREAMING_ACCEPTING; return; }