35 #include <libcjson/cJSON.h> 36 #include <libmediaprocsutils/uri_parser.h> 37 #include <libmediaprocsutils/log.h> 38 #include <libmediaprocsutils/stat_codes.h> 39 #include <libmediaprocsutils/check_utils.h> 40 #include <libmediaprocsutils/schedule.h> 41 #include <libmediaprocsutils/fair_lock.h> 42 #include <libmediaprocsutils/fifo.h> 43 #include <libmediaprocs/proc_if.h> 44 #include <libmediaprocs/procs.h> 45 #include <libmediaprocs/proc.h> 50 #include <liveMedia/liveMedia.hh> 51 #include <BasicUsageEnvironment/BasicUsageEnvironment.hh> 52 #ifndef _MULTI_FRAMED_RTP_SINK_HH 53 #include "MultiFramedRTPSink.hh" 60 #define SERVER_TOUT 10 62 #define FRAMED_SOURCE_FIFO_SLOTS 16 64 #define SINK_BUFFER_SIZE 200000 67 #ifdef ENABLE_DEBUG_LOGS 68 #define LOGD_CTX_INIT(CTX) LOG_CTX_INIT(CTX) 69 #define LOGD(FORMAT, ...) LOGV(FORMAT, ##__VA_ARGS__) 71 #define LOGD_CTX_INIT(CTX) 78 #define TAG_HAS(NEEDLE) (strstr(tag, NEEDLE)!= NULL) 83 #define TAG_IS(TAG) (strcmp(tag, TAG)== 0) 112 live555_rtsp_mux_settings_ctx;
171 live555_rtsp_es_mux_settings_ctx;
220 live555_rtsp_dmux_settings_ctx;
243 const char *settings_str,
log_ctx_t *log_ctx, va_list arg);
244 static int live555_rtsp_mux_init_given_settings(
258 static int live555_rtsp_mux_rest_get_es_array(
procs_ctx_t *procs_ctx_es_muxers,
259 cJSON **ref_cjson_es_array,
log_ctx_t *log_ctx);
267 static void* taskScheduler_thr(
void *t);
270 const char *settings_str,
log_ctx_t *log_ctx, va_list arg);
278 static int live555_rtsp_es_mux_settings_ctx_init(
280 live555_rtsp_es_mux_settings_ctx,
log_ctx_t *log_ctx);
281 static void live555_rtsp_es_mux_settings_ctx_deinit(
283 live555_rtsp_es_mux_settings_ctx,
log_ctx_t *log_ctx);
290 static SimpleRTPSink2* createNew(UsageEnvironment& env, Groupsock* RTPgs,
291 unsigned char rtpPayloadFormat,
unsigned rtpTimestampFrequency,
292 char const* sdpMediaTypeString,
char const* rtpPayloadFormatName,
293 unsigned numChannels= 1,
294 Boolean allowMultipleFramesPerPacket= True,
295 Boolean doNormalMBitRule= True);
299 unsigned char rtpPayloadFormat,
unsigned rtpTimestampFrequency,
300 char const* sdpMediaTypeString,
char const* rtpPayloadFormatName,
301 unsigned numChannels, Boolean allowMultipleFramesPerPacket,
302 Boolean doNormalMBitRule);
306 virtual void doSpecialFrameHandling(
unsigned fragmentationOffset,
307 unsigned char* frameStart,
308 unsigned numBytesInFrame,
309 struct timeval framePresentationTime,
310 unsigned numRemainingBytes);
311 virtual Boolean frameCanAppearAfterPacketStart(
312 unsigned char const* frameStart,
unsigned numBytesInFrame)
const;
313 virtual char const* sdpMediaType()
const;
316 char const* fSDPMediaTypeString;
317 Boolean fAllowMultipleFramesPerPacket;
318 Boolean fSetMBitOnLastFrames, fSetMBitOnNextPacket;
352 void doGetNextFrame();
356 static void deliverFrame0(
void* clientData);
370 const char *sdp_mimetype, portNumBits initialPortNum= 6970,
371 Boolean multiplexRTCPWithRTP= False);
377 portNumBits initialPortNum=6970,
378 Boolean multiplexRTCPWithRTP=False);
380 virtual FramedSource* createNewStreamSource(
unsigned clientSessionId,
381 unsigned& estBitrate);
382 virtual void deleteStream(
unsigned clientSessionId,
void*& streamToken);
383 virtual void closeStreamSource(FramedSource* inputSource);
384 virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,
385 unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource);
387 std::mutex m_simpleFramedSource_mutex;
389 const char *m_sdp_mimetype;
399 const char *settings_str,
log_ctx_t *log_ctx, va_list arg);
400 static int live555_rtsp_dmux_init_given_settings(
405 static void live555_rtsp_dmux_deinit_except_settings(
415 live555_rtsp_dmux_settings_ctx,
log_ctx_t *log_ctx);
418 live555_rtsp_dmux_settings_ctx,
log_ctx_t *log_ctx);
420 static void continueAfterDESCRIBE(RTSPClient *rtspClient,
int resultCode,
422 static void continueAfterSETUP(RTSPClient *rtspClient,
int resultCode,
424 static void continueAfterPLAY(RTSPClient *rtspClient,
int resultCode,
429 static void shutdownStream(RTSPClient* rtspClient,
int exitCode= 1);
440 virtual Boolean createSourceObjects(
int useSpecialRTPoffset);
453 char const* sdpDescription);
456 virtual MediaSubsession* createNewMediaSubsession();
469 MediaSubsessionIterator* iter;
471 MediaSubsession* subsession;
472 TaskToken streamTimerTask;
483 char const* rtspURL,
volatile int *ref_flag_exit,
485 char const* applicationName= NULL,
486 portNumBits tunnelOverHTTPPortNum= 0,
log_ctx_t *log_ctx= NULL);
489 volatile int *m_ref_flag_exit;
494 volatile int *ref_flag_exit,
fifo_ctx_t *fifo_ctx,
495 int verbosityLevel,
char const* applicationName,
496 portNumBits tunnelOverHTTPPortNum,
log_ctx_t *log_ctx= NULL);
511 static DummySink* createNew(UsageEnvironment& env,
512 MediaSubsession& subsession,
fifo_ctx_t *fifo_ctx,
513 char const* streamId= NULL,
log_ctx_t *log_ctx= NULL);
516 DummySink(UsageEnvironment& env, MediaSubsession& subsession,
520 static void afterGettingFrame(
void* clientData,
unsigned frameSize,
521 unsigned numTruncatedBytes,
522 struct timeval presentationTime,
523 unsigned durationInMicroseconds);
524 void afterGettingFrame(
unsigned frameSize,
unsigned numTruncatedBytes,
525 struct timeval presentationTime,
unsigned durationInMicroseconds);
527 virtual Boolean continuePlaying();
530 u_int8_t* fReceiveBuffer;
531 MediaSubsession& fSubsession;
536 std::mutex m_dummySink_io_mutex;
541 void live555_rtsp_reset_on_new_settings(
proc_ctx_t *proc_ctx,
543 void live555_rtsp_reset_on_new_settings_es_mux(
proc_ctx_t *proc_ctx,
545 void live555_rtsp_reset_on_new_settings_es_dmux(
proc_ctx_t *proc_ctx,
553 "live555_rtsp_mux",
"multiplexer",
"application/octet-stream",
557 proc_send_frame_default1,
570 static const proc_if_t proc_if_live555_rtsp_es_mux=
572 "live555_rtsp_es_mux",
"multiplexer",
"application/octet-stream",
574 live555_rtsp_es_mux_open,
576 proc_send_frame_default1,
591 "live555_rtsp_dmux",
"demultiplexer",
"application/octet-stream",
593 live555_rtsp_dmux_open,
597 proc_recv_frame_default1,
614 const char *settings_str,
log_ctx_t *log_ctx, va_list arg)
616 int ret_code, end_code= STAT_ERROR;
622 LOG_CTX_INIT(log_ctx);
625 CHECK_DO(proc_if!= NULL,
return NULL);
626 CHECK_DO(settings_str!= NULL,
return NULL);
632 CHECK_DO(live555_rtsp_mux_ctx!= NULL,
goto end);
635 live555_rtsp_mux_settings_ctx=
637 muxers_settings_mux_ctx=
643 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
648 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
653 ret_code= live555_rtsp_mux_init_given_settings(live555_rtsp_mux_ctx,
656 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
658 end_code= STAT_SUCCESS;
660 if(end_code!= STAT_SUCCESS)
665 static int live555_rtsp_mux_init_given_settings(
670 char *stream_session_name;
671 int ret_code, end_code= STAT_ERROR;
673 LOG_CTX_INIT(log_ctx);
676 CHECK_DO(live555_rtsp_mux_ctx!= NULL,
return STAT_ERROR);
677 CHECK_DO(muxers_settings_mux_ctx!= NULL,
return STAT_ERROR);
683 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
686 live555_rtsp_mux_ctx->
taskScheduler= BasicTaskScheduler::createNew();
701 port= muxers_settings_mux_ctx->
rtsp_port;
702 live555_rtsp_mux_ctx->
rtspServer= RTSPServer::createNew(
705 LOGE(
"Live555: %s\n",
720 stream_session_name!= NULL? stream_session_name:
"session",
723 live555_rtsp_mux_ctx->
rtspServer->addServerMediaSession(
728 &proc_if_live555_rtsp_es_mux);
729 CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_ECONFLICT,
goto end);
733 taskScheduler_thr, live555_rtsp_mux_ctx);
736 end_code= STAT_SUCCESS;
738 if(end_code!= STAT_SUCCESS)
752 LOGD(
">>%s\n", __FUNCTION__);
754 if(ref_proc_ctx== NULL)
758 LOG_CTX_SET(((
proc_ctx_t*)live555_rtsp_mux_ctx)->log_ctx);
769 free(live555_rtsp_mux_ctx);
772 LOGD(
"<<%s\n", __FUNCTION__);
782 void *thread_end_code= NULL;
784 LOG_CTX_INIT(log_ctx);
785 LOGD(
">>%s\n", __FUNCTION__);
788 if(live555_rtsp_mux_ctx== NULL)
799 ((
proc_ctx_t*)live555_rtsp_mux_ctx)->flag_exit= 1;
800 if(proc_muxer_mux_ctx!= NULL &&
803 LOGD(
"Waiting thread to join... ");
804 pthread_join(live555_rtsp_mux_ctx->taskScheduler_thread,
806 if(thread_end_code!= NULL) {
807 ASSERT(*((
int*)thread_end_code)== STAT_SUCCESS);
808 free(thread_end_code);
809 thread_end_code= NULL;
811 LOGD(
"joined O.K.\n");
824 if(live555_rtsp_mux_ctx->rtspServer!= NULL) {
825 Medium::close(live555_rtsp_mux_ctx->rtspServer);
826 live555_rtsp_mux_ctx->rtspServer= NULL;
829 if(live555_rtsp_mux_ctx->usageEnvironment!= NULL) {
830 Boolean ret_boolean= live555_rtsp_mux_ctx->usageEnvironment->reclaim();
831 ASSERT(ret_boolean== True);
832 if(ret_boolean== True)
833 live555_rtsp_mux_ctx->usageEnvironment= NULL;
836 if(live555_rtsp_mux_ctx->taskScheduler!= NULL) {
837 delete live555_rtsp_mux_ctx->taskScheduler;
838 live555_rtsp_mux_ctx->taskScheduler= NULL;
850 LOGD(
"<<%s\n", __FUNCTION__);
860 int ret_code, end_code= STAT_ERROR;
865 size_t fifo_elem_size= 0;
869 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
870 CHECK_DO(iput_fifo_ctx!= NULL,
return STAT_ERROR);
871 CHECK_DO(oput_fifo_ctx!= NULL,
return STAT_ERROR);
873 LOG_CTX_SET(proc_ctx->
log_ctx);
883 CHECK_DO(procs_ctx_es_muxers!= NULL,
goto end);
886 ret_code=
fifo_get(iput_fifo_ctx, (
void**)&proc_frame_ctx_iput,
888 CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN,
goto end);
889 if(ret_code== STAT_EAGAIN) {
897 proc_frame_ctx_iput);
898 CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN,
goto end);
900 end_code= STAT_SUCCESS;
902 if(proc_frame_ctx_iput!= NULL)
914 #define PROC_ID_STR_FMT "{\"elementary_stream_id\":%d}" 915 int ret_code, end_code= STAT_ERROR;
919 char *rest_str= NULL;
920 char ref_id_str[strlen(PROC_ID_STR_FMT)+ 64];
924 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
925 CHECK_DO(tag!= NULL,
return STAT_ERROR);
928 ret_code= pthread_mutex_trylock(&proc_ctx->
api_mutex);
929 CHECK_DO(ret_code== EBUSY,
return STAT_ERROR);
931 LOG_CTX_SET(proc_ctx->
log_ctx);
937 if(
TAG_IS(
"PROCS_ID_ES_MUX_REGISTER")) {
939 int elementary_stream_id= -1;
940 const char *settings_str= va_arg(arg,
const char*);
941 char **ref_rest_str= va_arg(arg,
char**);
943 end_code=
procs_opt(procs_ctx_es_muxers,
"PROCS_POST",
944 "live555_rtsp_es_mux", settings_str, &rest_str,
947 CHECK_DO(end_code== STAT_SUCCESS && rest_str!= NULL,
goto end);
950 p= strstr(rest_str,
"\"proc_id\":");
952 p+= strlen(
"\"proc_id\":");
953 elementary_stream_id= atoi(p);
954 CHECK_DO(elementary_stream_id>= 0,
goto end);
957 snprintf(ref_id_str,
sizeof(ref_id_str), PROC_ID_STR_FMT,
958 elementary_stream_id);
959 *ref_rest_str= strdup(ref_id_str);
961 LOGE(
"Unknown option\n");
962 end_code= STAT_ENOTFOUND;
969 #undef PROC_ID_STR_FMT 981 live555_rtsp_mux_settings_ctx= NULL;
986 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
987 CHECK_DO(str!= NULL,
return STAT_ERROR);
989 LOG_CTX_SET(proc_ctx->
log_ctx);
993 live555_rtsp_mux_settings_ctx=
995 muxers_settings_mux_ctx=
1001 if(ret_code!= STAT_SUCCESS)
1009 live555_rtsp_reset_on_new_settings(proc_ctx, 1, LOG_CTX_GET());
1011 return STAT_SUCCESS;
1021 int ret_code, end_code= STAT_ERROR;
1025 live555_rtsp_mux_settings_ctx= NULL;
1027 cJSON *cjson_rest= NULL, *cjson_settings= NULL, *cjson_es_array= NULL;
1031 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
1032 CHECK_DO(rest_fmt< PROC_IF_REST_FMT_ENUM_MAX,
return STAT_ERROR);
1033 CHECK_DO(ref_reponse!= NULL,
return STAT_ERROR);
1035 LOG_CTX_SET(proc_ctx->
log_ctx);
1040 cjson_rest= cJSON_CreateObject();
1041 CHECK_DO(cjson_rest!= NULL,
goto end);
1060 live555_rtsp_mux_settings_ctx=
1062 muxers_settings_mux_ctx=
1067 &cjson_settings, LOG_CTX_GET());
1068 CHECK_DO(ret_code== STAT_SUCCESS && cjson_settings!= NULL,
goto end);
1074 cJSON_AddItemToObject(cjson_rest,
"settings", cjson_settings);
1075 cjson_settings= NULL;
1081 live555_rtsp_mux_ctx)->procs_ctx_es_muxers;
1082 CHECK_DO(procs_ctx_es_muxers!= NULL,
goto end);
1083 ret_code= live555_rtsp_mux_rest_get_es_array(procs_ctx_es_muxers,
1084 &cjson_es_array, LOG_CTX_GET());
1085 CHECK_DO(ret_code== STAT_SUCCESS && cjson_es_array!= NULL,
goto end);
1086 cJSON_AddItemToObject(cjson_rest,
"elementary_streams", cjson_es_array);
1087 cjson_es_array= NULL;
1101 CHECK_DO(*ref_reponse!= NULL && strlen((
char*)*ref_reponse)> 0,
1105 *ref_reponse= (
void*)cjson_rest;
1109 LOGE(
"Unknown format requested for processor REST\n");
1113 end_code= STAT_SUCCESS;
1115 if(cjson_rest!= NULL)
1116 cJSON_Delete(cjson_rest);
1117 if(cjson_settings!= NULL)
1118 cJSON_Delete(cjson_settings);
1119 if(cjson_es_array!= NULL)
1120 cJSON_Delete(cjson_es_array);
1124 static int live555_rtsp_mux_rest_get_es_array(
procs_ctx_t *procs_ctx_es_muxers,
1125 cJSON **ref_cjson_es_array,
log_ctx_t *log_ctx)
1127 int i, ret_code, procs_num= 0, end_code= STAT_ERROR;
1128 cJSON *cjson_es_array= NULL, *cjson_procs_rest= NULL,
1129 *cjson_procs_es_rest= NULL, *cjson_procs_es_rest_settings= NULL;
1130 cJSON *cjson_procs= NULL, *cjson_aux= NULL;
1131 char *rest_str_aux= NULL, *es_rest_str_aux= NULL;
1132 LOG_CTX_INIT(log_ctx);
1135 CHECK_DO(procs_ctx_es_muxers!= NULL,
return STAT_ERROR);
1136 CHECK_DO(ref_cjson_es_array!= NULL,
return STAT_ERROR);
1138 *ref_cjson_es_array= NULL;
1141 cjson_es_array= cJSON_CreateArray();
1142 CHECK_DO(cjson_es_array!= NULL,
goto end);
1151 ret_code=
procs_opt(procs_ctx_es_muxers,
"PROCS_GET", &rest_str_aux, NULL);
1152 CHECK_DO(ret_code== STAT_SUCCESS && rest_str_aux!= NULL,
goto end);
1155 cjson_procs_rest= cJSON_Parse(rest_str_aux);
1156 CHECK_DO(cjson_procs_rest!= NULL,
goto end);
1159 cjson_procs= cJSON_GetObjectItem(cjson_procs_rest,
"procs");
1160 CHECK_DO(cjson_procs!= NULL,
goto end);
1161 procs_num= cJSON_GetArraySize(cjson_procs);
1162 for(i= 0; i< procs_num; i++) {
1164 cJSON *cjson_proc= cJSON_GetArrayItem(cjson_procs, i);
1165 CHECK_DO(cjson_proc!= NULL,
continue);
1167 cjson_aux= cJSON_GetObjectItem(cjson_proc,
"proc_id");
1168 CHECK_DO(cjson_aux!= NULL,
continue);
1169 elem_stream_id= (int)cjson_aux->valuedouble;
1172 if(es_rest_str_aux!= NULL) {
1173 free(es_rest_str_aux);
1174 es_rest_str_aux= NULL;
1176 ret_code=
procs_opt(procs_ctx_es_muxers,
"PROCS_ID_GET",
1177 elem_stream_id, &es_rest_str_aux);
1178 CHECK_DO(ret_code== STAT_SUCCESS && es_rest_str_aux!= NULL,
continue);
1181 if(cjson_procs_es_rest!= NULL) {
1182 cJSON_Delete(cjson_procs_es_rest);
1183 cjson_procs_es_rest= NULL;
1185 cjson_procs_es_rest= cJSON_Parse(es_rest_str_aux);
1186 CHECK_DO(cjson_procs_es_rest!= NULL,
continue);
1189 cjson_aux= cJSON_CreateNumber((
double)elem_stream_id);
1190 CHECK_DO(cjson_aux!= NULL,
continue);
1191 cJSON_AddItemToObject(cjson_procs_es_rest,
"elementary_stream_id",
1195 if(cjson_procs_es_rest_settings!= NULL) {
1196 cJSON_Delete(cjson_procs_es_rest_settings);
1197 cjson_procs_es_rest_settings= NULL;
1199 cjson_procs_es_rest_settings= cJSON_DetachItemFromObject(
1200 cjson_procs_es_rest,
"settings");
1203 cJSON_AddItemToArray(cjson_es_array, cjson_procs_es_rest);
1204 cjson_procs_es_rest= NULL;
1207 *ref_cjson_es_array= cjson_es_array;
1208 cjson_es_array= NULL;
1209 end_code= STAT_SUCCESS;
1211 if(cjson_es_array!= NULL)
1212 cJSON_Delete(cjson_es_array);
1213 if(rest_str_aux!= NULL)
1215 if(cjson_procs_rest!= NULL)
1216 cJSON_Delete(cjson_procs_rest);
1217 if(es_rest_str_aux!= NULL)
1218 free(es_rest_str_aux);
1219 if(cjson_procs_es_rest!= NULL)
1220 cJSON_Delete(cjson_procs_es_rest);
1221 if(cjson_procs_es_rest_settings!= NULL)
1222 cJSON_Delete(cjson_procs_es_rest_settings);
1239 LOG_CTX_INIT(log_ctx);
1242 CHECK_DO(live555_rtsp_mux_settings_ctx!= NULL,
return STAT_ERROR);
1244 muxers_settings_mux_ctx=
1249 if(ret_code!= STAT_SUCCESS)
1255 return STAT_SUCCESS;
1269 LOG_CTX_INIT(log_ctx);
1272 CHECK_DO(live555_rtsp_mux_settings_ctx!= NULL,
return);
1274 muxers_settings_mux_ctx=
1284 static void* taskScheduler_thr(
void *t)
1286 char volatile *watchVariable;
1288 int *ref_end_code= NULL;
1289 UsageEnvironment *usageEnvironment= NULL;
1293 ref_end_code= (
int*)malloc(
sizeof(
int));
1294 CHECK_DO(ref_end_code!= NULL,
return NULL);
1295 *ref_end_code= STAT_ERROR;
1298 CHECK_DO(live555_rtsp_mux_ctx!= NULL,
return (
void*)ref_end_code);
1300 LOG_CTX_SET(((
proc_ctx_t*)live555_rtsp_mux_ctx)->log_ctx);
1304 CHECK_DO(live555_rtsp_mux_ctx!= NULL,
return (
void*)ref_end_code);
1307 watchVariable= (
char volatile*)
1308 &((
proc_ctx_t*)live555_rtsp_mux_ctx)->flag_exit;
1309 usageEnvironment->taskScheduler().doEventLoop(watchVariable);
1311 *ref_end_code= STAT_SUCCESS;
1312 return (
void*)ref_end_code;
1318 const char *settings_str,
log_ctx_t *log_ctx, va_list arg)
1320 int ret_code, end_code= STAT_ERROR;
1323 live555_rtsp_es_mux_settings_ctx= NULL;
1324 UsageEnvironment *usageEnvironment= NULL;
1325 ServerMediaSession *serverMediaSession= NULL;
1326 LOG_CTX_INIT(log_ctx);
1329 CHECK_DO(proc_if!= NULL,
return NULL);
1330 CHECK_DO(settings_str!= NULL,
return NULL);
1336 CHECK_DO(live555_rtsp_es_mux_ctx!= NULL,
goto end);
1339 live555_rtsp_es_mux_settings_ctx=
1343 ret_code= live555_rtsp_es_mux_settings_ctx_init(
1344 live555_rtsp_es_mux_settings_ctx, LOG_CTX_GET());
1345 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
1349 live555_rtsp_es_mux_ctx, settings_str);
1350 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
1354 live555_rtsp_es_mux_ctx->
log_ctx= LOG_CTX_GET();
1356 usageEnvironment= va_arg(arg, UsageEnvironment*);
1357 CHECK_DO(usageEnvironment!= NULL,
goto end);
1359 serverMediaSession= va_arg(arg, ServerMediaSession*);
1360 CHECK_DO(serverMediaSession!= NULL,
goto end);
1363 &(usageEnvironment->taskScheduler());
1367 SimpleMediaSubsession::createNew(*usageEnvironment,
1371 ret_code= serverMediaSession->addSubsession(
1373 CHECK_DO(ret_code== True,
goto end);
1375 end_code= STAT_SUCCESS;
1377 if(end_code!= STAT_SUCCESS)
1390 LOGD(
">>%s\n", __FUNCTION__);
1392 if(ref_proc_ctx== NULL)
1397 LOG_CTX_SET(((
proc_ctx_t*)live555_rtsp_es_mux_ctx)->log_ctx);
1400 live555_rtsp_es_mux_settings_ctx_deinit(
1407 free(live555_rtsp_es_mux_ctx);
1408 *ref_proc_ctx= NULL;
1410 LOGD(
"<<%s\n", __FUNCTION__);
1420 int ret_code, end_code= STAT_ERROR;
1423 size_t fifo_elem_size= 0;
1428 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
1429 CHECK_DO(iput_fifo_ctx!= NULL,
return STAT_ERROR);
1430 CHECK_DO(oput_fifo_ctx!= NULL,
return STAT_ERROR);
1432 LOG_CTX_SET(proc_ctx->
log_ctx);
1438 ret_code=
fifo_get(iput_fifo_ctx, (
void**)&proc_frame_ctx, &fifo_elem_size);
1439 CHECK_DO(ret_code== STAT_SUCCESS || ret_code== STAT_EAGAIN,
goto end);
1440 if(ret_code== STAT_EAGAIN) {
1449 CHECK_DO(simpleMediaSubsession!= NULL,
goto end);
1450 simpleMediaSubsession->deliverFrame(&proc_frame_ctx);
1452 end_code= STAT_SUCCESS;
1458 if(proc_frame_ctx!= NULL) {
1471 int flag_is_query, end_code= STAT_ERROR;
1474 live555_rtsp_es_mux_settings_ctx= NULL;
1475 char *sdp_mimetype_str= NULL, *rtp_timestamp_freq_str= NULL,
1476 *bit_rate_estimated_str= NULL;
1477 cJSON *cjson_rest= NULL, *cjson_aux= NULL;
1481 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
1482 CHECK_DO(str!= NULL,
return STAT_ERROR);
1484 LOG_CTX_SET(proc_ctx->
log_ctx);
1488 live555_rtsp_es_mux_settings_ctx=
1495 flag_is_query= (str[0]==
'{' && str[strlen(str)-1]==
'}')? 0: 1;
1499 if(flag_is_query== 1) {
1502 sdp_mimetype_str= uri_parser_query_str_get_value(
"sdp_mimetype", str);
1503 if(sdp_mimetype_str!= NULL) {
1505 CHECK_DO(strlen(sdp_mimetype_str)> 0,
1506 end_code= STAT_EINVAL;
goto end);
1509 sdp_mimetype= strdup(sdp_mimetype_str);
1510 CHECK_DO(sdp_mimetype!= NULL,
goto end);
1513 if(live555_rtsp_es_mux_settings_ctx->
sdp_mimetype!= NULL)
1515 live555_rtsp_es_mux_settings_ctx->
sdp_mimetype= sdp_mimetype;
1519 rtp_timestamp_freq_str= uri_parser_query_str_get_value(
1520 "rtp_timestamp_freq", str);
1521 if(rtp_timestamp_freq_str!= NULL)
1523 atoll(rtp_timestamp_freq_str);
1527 cjson_rest= cJSON_Parse(str);
1528 CHECK_DO(cjson_rest!= NULL,
goto end);
1531 cjson_aux= cJSON_GetObjectItem(cjson_rest,
"sdp_mimetype");
1532 if(cjson_aux!= NULL) {
1534 CHECK_DO(strlen(cjson_aux->valuestring)> 0,
1535 end_code= STAT_EINVAL;
goto end);
1538 sdp_mimetype= strdup(cjson_aux->valuestring);
1539 CHECK_DO(sdp_mimetype!= NULL,
goto end);
1542 if(live555_rtsp_es_mux_settings_ctx->
sdp_mimetype!= NULL)
1544 live555_rtsp_es_mux_settings_ctx->
sdp_mimetype= sdp_mimetype;
1548 cjson_aux= cJSON_GetObjectItem(cjson_rest,
"rtp_timestamp_freq");
1549 if(cjson_aux!= NULL)
1551 cjson_aux->valuedouble;
1557 end_code= STAT_SUCCESS;
1559 if(sdp_mimetype_str!= NULL)
1560 free(sdp_mimetype_str);
1561 if(rtp_timestamp_freq_str!= NULL)
1562 free(rtp_timestamp_freq_str);
1563 if(bit_rate_estimated_str!= NULL)
1564 free(bit_rate_estimated_str);
1565 if(cjson_rest!= NULL)
1566 cJSON_Delete(cjson_rest);
1577 int end_code= STAT_ERROR;
1580 live555_rtsp_es_mux_settings_ctx= NULL;
1581 cJSON *cjson_rest= NULL;
1582 cJSON *cjson_aux= NULL;
1586 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
1587 CHECK_DO(rest_fmt< PROC_IF_REST_FMT_ENUM_MAX,
return STAT_ERROR);
1588 CHECK_DO(ref_reponse!= NULL,
return STAT_ERROR);
1590 LOG_CTX_SET(proc_ctx->
log_ctx);
1595 cjson_rest= cJSON_CreateObject();
1596 CHECK_DO(cjson_rest!= NULL,
goto end);
1609 live555_rtsp_es_mux_settings_ctx=
1625 cjson_aux= cJSON_CreateString(
1627 CHECK_DO(cjson_aux!= NULL,
goto end);
1628 cJSON_AddItemToObject(cjson_rest,
"sdp_mimetype", cjson_aux);
1631 cjson_aux= cJSON_CreateNumber((
double)
1633 CHECK_DO(cjson_aux!= NULL,
goto end);
1634 cJSON_AddItemToObject(cjson_rest,
"rtp_timestamp_freq", cjson_aux);
1650 CHECK_DO(*ref_reponse!= NULL && strlen((
char*)*ref_reponse)> 0,
1654 *ref_reponse= (
void*)cjson_rest;
1658 LOGE(
"Unknown format requested for processor REST\n");
1662 end_code= STAT_SUCCESS;
1666 if(cjson_rest!= NULL)
1667 cJSON_Delete(cjson_rest);
1671 static int live555_rtsp_es_mux_settings_ctx_init(
1673 live555_rtsp_es_mux_settings_ctx,
log_ctx_t *log_ctx)
1675 LOG_CTX_INIT(log_ctx);
1678 CHECK_DO(live555_rtsp_es_mux_settings_ctx!= NULL,
return STAT_ERROR);
1680 live555_rtsp_es_mux_settings_ctx->
sdp_mimetype= strdup(
"n/a");
1685 return STAT_SUCCESS;
1688 static void live555_rtsp_es_mux_settings_ctx_deinit(
1690 live555_rtsp_es_mux_settings_ctx,
log_ctx_t *log_ctx)
1692 LOG_CTX_INIT(log_ctx);
1695 CHECK_DO(live555_rtsp_es_mux_settings_ctx!= NULL,
return);
1698 if(live555_rtsp_es_mux_settings_ctx->
sdp_mimetype!= NULL) {
1706 SimpleRTPSink2::SimpleRTPSink2(UsageEnvironment& env, Groupsock* RTPgs,
1707 unsigned char rtpPayloadFormat,
unsigned rtpTimestampFrequency,
1708 char const* sdpMediaTypeString,
char const* rtpPayloadFormatName,
1709 unsigned numChannels, Boolean allowMultipleFramesPerPacket,
1710 Boolean doNormalMBitRule):
1711 MultiFramedRTPSink(env, RTPgs, rtpPayloadFormat,
1712 rtpTimestampFrequency, rtpPayloadFormatName,
1714 fAllowMultipleFramesPerPacket(allowMultipleFramesPerPacket),
1715 fSetMBitOnNextPacket(False)
1717 fSDPMediaTypeString= strDup(
1718 sdpMediaTypeString== NULL?
"unknown": sdpMediaTypeString);
1719 fSetMBitOnLastFrames= doNormalMBitRule
1723 SimpleRTPSink2::~SimpleRTPSink2()
1725 delete[] (
char*)fSDPMediaTypeString;
1729 UsageEnvironment& env, Groupsock* RTPgs,
1730 unsigned char rtpPayloadFormat,
unsigned rtpTimestampFrequency,
1731 char const* sdpMediaTypeString,
char const* rtpPayloadFormatName,
1732 unsigned numChannels, Boolean allowMultipleFramesPerPacket,
1733 Boolean doNormalMBitRule)
1736 rtpTimestampFrequency, sdpMediaTypeString, rtpPayloadFormatName,
1737 numChannels, allowMultipleFramesPerPacket, doNormalMBitRule);
1740 void SimpleRTPSink2::doSpecialFrameHandling(
unsigned fragmentationOffset,
1741 unsigned char* frameStart,
1742 unsigned numBytesInFrame,
1743 struct timeval framePresentationTime,
1744 unsigned numRemainingBytes) {
1745 if(numRemainingBytes== 0) {
1748 if(fSetMBitOnLastFrames)
1751 if(fSetMBitOnNextPacket) {
1754 fSetMBitOnNextPacket = False;
1759 MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset,
1760 frameStart, numBytesInFrame, framePresentationTime,
1764 Boolean SimpleRTPSink2::frameCanAppearAfterPacketStart(
1765 unsigned char const* ,
unsigned )
1768 return fAllowMultipleFramesPerPacket;
1771 char const* SimpleRTPSink2::sdpMediaType()
const 1773 return fSDPMediaTypeString;
1784 SimpleFramedSource::SimpleFramedSource(UsageEnvironment& env,
1790 LOG_CTX_INIT(m_log_ctx);
1791 LOGD(
">>::SimpleFramedSource\n");
1794 fifo_elem_alloc_fxn.elem_ctx_dup=
1796 fifo_elem_alloc_fxn.elem_ctx_release=
1798 m_fifo_ctx=
fifo_open(FRAMED_SOURCE_FIFO_SLOTS, 0,
1800 ASSERT(m_fifo_ctx!= NULL);
1805 m_eventTriggerId= envir().taskScheduler().createEventTrigger(deliverFrame0);
1807 LOGD(
"<<::SimpleFramedSource\n");
1810 SimpleFramedSource::~SimpleFramedSource()
1812 LOGD_CTX_INIT(m_log_ctx);
1813 LOGD(
">>::~SimpleFramedSource\n");
1819 envir().taskScheduler().deleteEventTrigger(m_eventTriggerId);
1820 m_eventTriggerId= 0;
1822 LOGD(
"<<::~SimpleFramedSource\n");
1825 void SimpleFramedSource::doGetNextFrame()
1827 LOGD_CTX_INIT(m_log_ctx);
1828 LOGD(
">>SimpleFramedSource::doGetNextFrame\n");
1844 LOGD(
"<<SimpleFramedSource::doGetNextFrame\n");
1847 void SimpleFramedSource::deliverFrame0(
void *simpleFramedSource_opaque)
1849 LOGD_CTX_INIT(NULL);
1850 LOGD(
">>%s\n", __FUNCTION__);
1852 LOGD(
"<<%s\n", __FUNCTION__);
1881 uint8_t *newFrame= NULL;
1882 int ret_code, newFrameSize= 0;
1884 size_t fifo_elem_size= 0;
1885 LOG_CTX_INIT(m_log_ctx);
1886 LOGD(
">>%s\n", __FUNCTION__);
1888 if(!isCurrentlyAwaitingData()) {
1889 LOGD(
"-!isCurrentlyAwaitingData()-");
1899 ret_code=
fifo_show(m_fifo_ctx, (
void**)&proc_frame_ctx_show,
1901 CHECK_DO(ret_code== STAT_SUCCESS && proc_frame_ctx_show!= NULL,
goto end);
1904 newFrame= (uint8_t*)proc_frame_ctx_show->
p_data[0];
1905 newFrameSize= proc_frame_ctx_show->
width[0];
1906 if(newFrameSize> (
int)fMaxSize) {
1907 LOGW(
"Input frame fragmented (Elementary Stream Id.: %d\n)",
1908 proc_frame_ctx_show->
es_id);
1909 fFrameSize= fMaxSize;
1910 fNumTruncatedBytes= newFrameSize- fMaxSize;
1912 proc_frame_ctx_show->
p_data[0]= (
const uint8_t*)(newFrame+ fMaxSize);
1913 proc_frame_ctx_show->
width[0]-= fMaxSize;
1915 fFrameSize= newFrameSize;
1916 fNumTruncatedBytes= 0;
1918 gettimeofday(&fPresentationTime, NULL);
1921 memmove(fTo, newFrame, fFrameSize);
1924 FramedSource::afterGetting(
this);
1927 if(fNumTruncatedBytes== 0) {
1929 ret_code=
fifo_get(m_fifo_ctx, (
void**)&proc_frame_ctx,
1931 ASSERT(ret_code== STAT_SUCCESS);
1936 LOGD(
"<<%s\n", __FUNCTION__);
1943 const char *sdp_mimetype, portNumBits initialPortNum,
1944 Boolean multiplexRTCPWithRTP)
1947 multiplexRTCPWithRTP);
1950 SimpleMediaSubsession::SimpleMediaSubsession(UsageEnvironment &env,
1951 const char *sdp_mimetype, portNumBits initialPortNum,
1952 Boolean multiplexRTCPWithRTP):
1953 OnDemandServerMediaSubsession(env, True,
1954 initialPortNum, multiplexRTCPWithRTP),
1955 m_simpleFramedSource(NULL),
1958 LOGD_CTX_INIT(m_log_ctx);
1959 LOGD(
">>::SimpleMediaSubsession\n");
1962 if(sdp_mimetype!= NULL && strlen(sdp_mimetype)> 0)
1963 m_sdp_mimetype= sdp_mimetype;
1965 m_sdp_mimetype= (
const char*)
"n/a";
1967 LOGD(
"<<::SimpleMediaSubsession\n");
1970 void SimpleMediaSubsession::deliverFrame(
proc_frame_ctx_t **ref_proc_frame_ctx)
1972 LOG_CTX_INIT(m_log_ctx);
1975 CHECK_DO(ref_proc_frame_ctx!= NULL && *ref_proc_frame_ctx!= NULL,
return);
1977 m_simpleFramedSource_mutex.lock();
1979 if(m_simpleFramedSource!= NULL) {
1983 ret_code=
fifo_put(m_simpleFramedSource->m_fifo_ctx,
1984 (
void**)ref_proc_frame_ctx,
sizeof(
void*));
1985 if(ret_code== STAT_ENOMEM)
1986 LOGW(
"MUXER buffer overflow: throughput may be exceeding " 1987 "processing capacity?\n");
1989 ASSERT(*ref_proc_frame_ctx== NULL);
2001 envir().taskScheduler().triggerEvent(
2002 m_simpleFramedSource->m_eventTriggerId, m_simpleFramedSource);
2005 m_simpleFramedSource_mutex.unlock();
2013 FramedSource* SimpleMediaSubsession::createNewStreamSource(
2014 unsigned clientSessionId,
unsigned &estBitrate)
2016 FramedSource *framedSource= NULL;
2017 LOG_CTX_INIT(m_log_ctx);
2019 LOGD(
">> SimpleMediaSubsession::createNewStreamSource\n");
2022 OutPacketBuffer::increaseMaxSizeTo(SINK_BUFFER_SIZE);
2025 framedSource= SimpleFramedSource::createNew(envir(), LOG_CTX_GET());
2026 m_simpleFramedSource_mutex.lock();
2028 m_simpleFramedSource_mutex.unlock();
2032 LOGD(
"<< SimpleMediaSubsession::createNewStreamSource\n");
2033 return framedSource;
2036 void SimpleMediaSubsession::deleteStream(
unsigned clientSessionId,
2039 LOGD_CTX_INIT(m_log_ctx);
2041 LOGD(
">> SimpleMediaSubsession::deleteStream\n");
2042 m_simpleFramedSource_mutex.lock();
2043 m_simpleFramedSource= NULL;
2044 m_simpleFramedSource_mutex.unlock();
2045 OnDemandServerMediaSubsession::deleteStream(clientSessionId, streamToken);
2046 LOGD(
"<< SimpleMediaSubsession::deleteStream\n");
2049 void SimpleMediaSubsession::closeStreamSource(FramedSource* inputSource)
2051 LOGD_CTX_INIT(m_log_ctx);
2052 LOGD(
">> SimpleMediaSubsession::closeStreamSource\n");
2053 m_simpleFramedSource_mutex.lock();
2054 m_simpleFramedSource= NULL;
2055 m_simpleFramedSource_mutex.unlock();
2056 OnDemandServerMediaSubsession::closeStreamSource(inputSource);
2057 LOGD(
"<< SimpleMediaSubsession::closeStreamSource\n");
2060 RTPSink* SimpleMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock,
2061 unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource)
2064 RTPSink *rtpSink= NULL;
2065 char *type_str= NULL, *subtype_str= NULL;
2066 LOG_CTX_INIT(m_log_ctx);
2067 LOGD(
">>SimpleMediaSubsession::createNewRTPSink\n");
2070 CHECK_DO(m_sdp_mimetype!= NULL,
goto end);
2073 sdp_p= strchr((
char*)m_sdp_mimetype,
'/');
2074 if(sdp_p!= NULL && strlen(m_sdp_mimetype)> 0)
2075 type_str= strndup(m_sdp_mimetype, sdp_p- m_sdp_mimetype);
2077 type_str= strdup(
"n/a");
2078 if(sdp_p!= NULL && strlen(sdp_p+ 1)> 0)
2079 subtype_str= strdup(sdp_p+ 1);
2081 subtype_str= strdup(
"n/a");
2090 rtpSink= SimpleRTPSink2::createNew(envir(), rtpGroupsock,
2091 rtpPayloadTypeIfDynamic, 90000, type_str, subtype_str,
2098 if(subtype_str!= NULL)
2100 LOGD(
"<<SimpleMediaSubsession::createNewRTPSink\n");
2111 const char *settings_str,
log_ctx_t *log_ctx, va_list arg)
2113 int ret_code, end_code= STAT_ERROR;
2119 LOG_CTX_INIT(log_ctx);
2122 CHECK_DO(proc_if!= NULL,
return NULL);
2123 CHECK_DO(settings_str!= NULL,
return NULL);
2129 CHECK_DO(live555_rtsp_dmux_ctx!= NULL,
goto end);
2132 live555_rtsp_dmux_settings_ctx=
2134 muxers_settings_dmux_ctx=
2139 live555_rtsp_dmux_settings_ctx, LOG_CTX_GET());
2140 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
2145 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
2150 ret_code= live555_rtsp_dmux_init_given_settings(live555_rtsp_dmux_ctx,
2153 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
2155 end_code= STAT_SUCCESS;
2157 if(end_code!= STAT_SUCCESS)
2162 static int live555_rtsp_dmux_init_given_settings(
2167 int end_code= STAT_ERROR;
2168 LOG_CTX_INIT(log_ctx);
2171 CHECK_DO(live555_rtsp_dmux_ctx!= NULL,
return STAT_ERROR);
2172 CHECK_DO(muxers_settings_dmux_ctx!= NULL,
return STAT_ERROR);
2176 live555_rtsp_dmux_ctx->
taskScheduler= BasicTaskScheduler::createNew();
2186 end_code= STAT_SUCCESS;
2188 if(end_code!= STAT_SUCCESS)
2189 live555_rtsp_dmux_deinit_except_settings(live555_rtsp_dmux_ctx,
2202 LOGD(
">> %s\n", __FUNCTION__);
2204 if(ref_proc_ctx== NULL)
2209 LOG_CTX_SET(((
proc_ctx_t*)live555_rtsp_dmux_ctx)->log_ctx);
2224 live555_rtsp_dmux_deinit_except_settings(live555_rtsp_dmux_ctx,
2229 free(live555_rtsp_dmux_ctx);
2230 *ref_proc_ctx= NULL;
2232 LOGD(
"<< %s\n", __FUNCTION__);
2235 static void live555_rtsp_dmux_deinit_except_settings(
2238 LOG_CTX_INIT(log_ctx);
2240 if(live555_rtsp_dmux_ctx== NULL)
2245 ASSERT(ret_boolean== True);
2246 if(ret_boolean== True)
2263 int end_code= STAT_ERROR;
2269 MediaSession* session= NULL;
2270 cJSON *cjson_rest= NULL, *cjson_settings= NULL, *cjson_es_array= NULL,
2272 cJSON *cjson_aux= NULL;
2273 char sdp_mimetype_buf[512];
2277 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
2278 CHECK_DO(rest_fmt< PROC_IF_REST_FMT_ENUM_MAX,
return STAT_ERROR);
2279 CHECK_DO(ref_reponse!= NULL,
return STAT_ERROR);
2281 LOG_CTX_SET(proc_ctx->
log_ctx);
2286 cjson_rest= cJSON_CreateObject();
2287 CHECK_DO(cjson_rest!= NULL,
goto end);
2310 live555_rtsp_dmux_settings_ctx=
2312 muxers_settings_dmux_ctx=
2318 cjson_settings= cJSON_CreateObject();
2319 CHECK_DO(cjson_settings!= NULL,
goto end);
2322 cjson_aux= cJSON_CreateString(muxers_settings_dmux_ctx->
rtsp_url);
2323 CHECK_DO(cjson_aux!= NULL,
goto end);
2324 cJSON_AddItemToObject(cjson_settings,
"rtsp_url", cjson_aux);
2327 cJSON_AddItemToObject(cjson_rest,
"settings", cjson_settings);
2328 cjson_settings= NULL;
2333 cjson_es_array= cJSON_CreateArray();
2334 CHECK_DO(cjson_es_array!= NULL,
goto end);
2337 CHECK_DO(simpleRTSPClient!= NULL,
goto end);
2339 session= simpleRTSPClient->streamClientState.session;
2340 if(session!= NULL) {
2341 MediaSubsession *subsession= NULL;
2342 MediaSubsessionIterator iter(*session);
2343 while((subsession= iter.next())!= NULL && proc_ctx->
flag_exit== 0) {
2346 if(cjson_es!= NULL) {
2347 cJSON_Delete(cjson_es);
2350 cjson_es= cJSON_CreateObject();
2351 CHECK_DO(cjson_es!= NULL,
goto end);
2354 memset(sdp_mimetype_buf, 0,
sizeof(sdp_mimetype_buf));
2355 snprintf(sdp_mimetype_buf,
sizeof(sdp_mimetype_buf),
"%s/%s",
2356 subsession->mediumName(), subsession->codecName());
2357 cjson_aux= cJSON_CreateString(sdp_mimetype_buf);
2358 CHECK_DO(cjson_aux!= NULL,
goto end);
2359 cJSON_AddItemToObject(cjson_es,
"sdp_mimetype", cjson_aux);
2362 cjson_aux= cJSON_CreateNumber((
double)subsession->clientPortNum());
2363 CHECK_DO(cjson_aux!= NULL,
goto end);
2364 cJSON_AddItemToObject(cjson_es,
"port", cjson_aux);
2367 cjson_aux= cJSON_CreateNumber((
double)subsession->clientPortNum());
2368 CHECK_DO(cjson_aux!= NULL,
goto end);
2369 cJSON_AddItemToObject(cjson_es,
"elementary_stream_id", cjson_aux);
2372 cJSON_AddItemToArray(cjson_es_array, cjson_es);
2378 cJSON_AddItemToObject(cjson_rest,
"elementary_streams", cjson_es_array);
2379 cjson_es_array= NULL;
2395 CHECK_DO(*ref_reponse!= NULL && strlen((
char*)*ref_reponse)> 0,
2399 *ref_reponse= (
void*)cjson_rest;
2403 LOGE(
"Unknown format requested for processor REST\n");
2407 end_code= STAT_SUCCESS;
2409 if(cjson_settings!= NULL)
2410 cJSON_Delete(cjson_settings);
2411 if(cjson_rest!= NULL)
2412 cJSON_Delete(cjson_rest);
2413 if(cjson_es_array!= NULL)
2414 cJSON_Delete(cjson_es_array);
2416 cJSON_Delete(cjson_es);
2428 char volatile *watchVariable;
2429 int ret_code, end_code= STAT_ERROR;
2435 UsageEnvironment *usageEnvironment= NULL;
2439 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
2440 CHECK_DO(iput_fifo_ctx!= NULL,
return STAT_ERROR);
2441 CHECK_DO(oput_fifo_ctx!= NULL,
return STAT_ERROR);
2443 LOG_CTX_SET(proc_ctx->
log_ctx);
2450 CHECK_DO(usageEnvironment!= NULL,
goto end);
2453 live555_rtsp_dmux_settings_ctx=
2455 muxers_settings_dmux_ctx=
2461 rtsp_url= muxers_settings_dmux_ctx->
rtsp_url;
2462 if(rtsp_url== NULL) {
2463 LOGE(
"A valid RTSP URL must be provided\n");
2468 &((
proc_ctx_t*)live555_rtsp_dmux_ctx)->flag_exit,
2469 ((
proc_ctx_t*)live555_rtsp_dmux_ctx)->fifo_ctx_array[PROC_OPUT],
2470 0,
"n/a", 0, LOG_CTX_GET());
2472 LOGE(
"Failed to create a RTSP client for URL %s: %s\n", rtsp_url,
2485 continueAfterDESCRIBE);
2487 LOGE(
"Failed to send DESCRIBE to RTSP client for URL %s: %s\n",
2501 watchVariable= (
char volatile*)
2502 &((
proc_ctx_t*)live555_rtsp_dmux_ctx)->flag_exit;
2503 usageEnvironment->taskScheduler().doEventLoop(watchVariable);
2505 end_code= STAT_SUCCESS;
2521 live555_rtsp_dmux_settings_ctx= NULL;
2526 CHECK_DO(proc_ctx!= NULL,
return STAT_ERROR);
2527 CHECK_DO(str!= NULL,
return STAT_ERROR);
2529 LOG_CTX_SET(proc_ctx->
log_ctx);
2533 live555_rtsp_dmux_settings_ctx=
2535 muxers_settings_dmux_ctx=
2540 str, LOG_CTX_GET());
2541 if(ret_code!= STAT_SUCCESS)
2549 live555_rtsp_reset_on_new_settings(proc_ctx, 0, LOG_CTX_GET());
2551 return STAT_SUCCESS;
2563 live555_rtsp_dmux_settings_ctx,
log_ctx_t *log_ctx)
2567 LOG_CTX_INIT(log_ctx);
2570 CHECK_DO(live555_rtsp_dmux_settings_ctx!= NULL,
return STAT_ERROR);
2572 muxers_settings_dmux_ctx=
2577 if(ret_code!= STAT_SUCCESS)
2583 return STAT_SUCCESS;
2594 live555_rtsp_dmux_settings_ctx,
log_ctx_t *log_ctx)
2597 LOG_CTX_INIT(log_ctx);
2600 CHECK_DO(live555_rtsp_dmux_settings_ctx!= NULL,
return);
2602 muxers_settings_dmux_ctx=
2612 static void continueAfterDESCRIBE(RTSPClient *rtspClient,
int resultCode,
2615 int end_code= STAT_ERROR;
2616 UsageEnvironment *usageEnvironment= NULL;
2621 CHECK_DO(rtspClient!= NULL,
goto end);
2622 usageEnvironment= &rtspClient->envir();
2624 if(resultCode!= 0) {
2625 LOGE(
"[URL: '%s'] Failed to get a SDP description: \n",
2626 rtspClient->url(), resultString);
2635 LOGW(
"Got a SDP description: %s\n", resultString);
2636 streamClientState->session = SimpleClientSession::createNew(
2637 *usageEnvironment, resultString);
2638 if(streamClientState->session== NULL) {
2639 LOGE(
"[URL: '%s'] Failed to create a MediaSession object from the SDP " 2640 "description: %s\n", rtspClient->url(),
2641 usageEnvironment->getResultMsg());
2643 }
else if(!streamClientState->session->hasSubsessions()) {
2644 LOGE(
"[URL: '%s'] This session has no media subsessions (i.e. no 'm=' " 2645 "lines)\n", rtspClient->url());
2654 streamClientState->iter=
new MediaSubsessionIterator(
2655 *streamClientState->session);
2658 end_code= STAT_SUCCESS;
2660 if(end_code!= STAT_SUCCESS)
2662 if(resultString!= NULL)
2663 delete[] resultString;
2672 UsageEnvironment *usageEnvironment= NULL;
2674 MediaSubsession *subsession= NULL;
2675 MediaSession *session= NULL;
2676 char extra_port_str[8]= {0};
2680 CHECK_DO(rtspClient!= NULL,
return);
2682 usageEnvironment= &rtspClient->envir();
2685 streamClientState->subsession= subsession= streamClientState->iter->next();
2686 if(subsession!= NULL) {
2687 unsigned short port;
2690 if(!subsession->initiate(0)) {
2691 LOGE(
"[URL: '%s'] Failed to initiate the sub-session '%s/%s': %s\n",
2692 rtspClient->url(), subsession->mediumName(),
2693 subsession->codecName(), usageEnvironment->getResultMsg());
2698 port= subsession->clientPortNum();
2699 snprintf(extra_port_str,
sizeof(extra_port_str),
", %d", port+ 1);
2700 LOGW(
"[URL: '%s'] Initiated the sub-session '%s/%s' (client port[s] " 2701 "%d%s)\n", rtspClient->url(), subsession->mediumName(),
2702 subsession->codecName(), port,
2703 !subsession->rtcpIsMuxed()? extra_port_str:
"");
2708 rtspClient->sendSetupCommand(*subsession, continueAfterSETUP, False,
2716 if((session= streamClientState->session)!= NULL) {
2717 char* absStartTime_str= session->absStartTime();
2718 if(absStartTime_str!= NULL) {
2722 rtspClient->sendPlayCommand(*session, continueAfterPLAY,
2723 absStartTime_str, session->absEndTime());
2725 streamClientState->duration= session->playEndTime()-
2726 session->playStartTime();
2727 rtspClient->sendPlayCommand(*session, continueAfterPLAY);
2733 static void continueAfterSETUP(RTSPClient *rtspClient,
int resultCode,
2736 unsigned short port;
2737 UsageEnvironment *usageEnvironment= NULL;
2739 MediaSubsession *subsession= NULL;
2740 RTCPInstance *rtcpInstance= NULL;
2741 char extra_port_str[8]= {0};
2745 CHECK_DO(rtspClient!= NULL,
goto end);
2746 usageEnvironment= &rtspClient->envir();
2748 subsession= streamClientState->subsession;
2749 CHECK_DO(subsession!= NULL,
goto end);
2750 if(resultCode!= 0) {
2751 LOGE(
"[URL: '%s'] Failed to set up the sub-session '%s/%s': %s\n",
2752 rtspClient->url(), subsession->mediumName(),
2753 subsession->codecName(), resultString);
2757 port= subsession->clientPortNum();
2758 snprintf(extra_port_str,
sizeof(extra_port_str),
", %d", port+ 1);
2759 LOGW(
"[URL: '%s'] Set up the sub-session '%s/%s' (client port[s] %d%s)\n",
2760 rtspClient->url(), subsession->mediumName(),
2761 subsession->codecName(), port,
2762 !subsession->rtcpIsMuxed()? extra_port_str:
"");
2772 CHECK_DO(subsession->sink!= NULL,
goto end);
2775 subsession->miscPtr= rtspClient;
2776 subsession->sink->startPlaying(*(subsession->readSource()),
2780 if((rtcpInstance= subsession->rtcpInstance())!= NULL)
2785 if(resultString!= NULL)
2786 delete[] resultString;
2790 static void continueAfterPLAY(RTSPClient *rtspClient,
int resultCode,
2793 int end_code= STAT_ERROR;
2797 CHECK_DO(rtspClient!= NULL,
goto end);
2798 if(resultCode!= 0) {
2799 LOGE(
"[URL: '%s'] Failed to start playing session: %s\n",
2800 rtspClient->url(), resultString);
2804 LOGW(
"[URL: '%s'] Started playing session...\n", rtspClient->url());
2806 end_code= STAT_SUCCESS;
2808 if(end_code!= STAT_SUCCESS)
2810 if(resultString!= NULL)
2811 delete[] resultString;
2820 MediaSubsession *subsession= NULL;
2821 RTSPClient *rtspClient= NULL;
2825 CHECK_DO(clientData!= NULL,
return);
2827 subsession= (MediaSubsession*)clientData;
2828 rtspClient= (RTSPClient*)(subsession->miscPtr);
2831 Medium::close(subsession->sink);
2832 subsession->sink= NULL;
2835 MediaSession& session= subsession->parentSession();
2836 MediaSubsessionIterator iter(session);
2837 while((subsession= iter.next())!= NULL) {
2838 if(subsession->sink!= NULL)
return;
2850 MediaSubsession *subsession= NULL;
2851 RTSPClient *rtspClient= NULL;
2855 CHECK_DO(clientData!= NULL,
return);
2857 subsession= (MediaSubsession*)clientData;
2858 rtspClient= (RTSPClient*)(subsession->miscPtr);
2860 LOGW(
"[URL: '%s'] Received RTCP 'BYE' on sub-session '%s/%s'\n",
2861 rtspClient->url(), subsession->mediumName(),
2862 subsession->codecName());
2874 MediaSession *session= NULL;
2878 CHECK_DO(rtspClient!= NULL,
return);
2883 if((session= streamClientState->session)!= NULL) {
2884 Boolean someSubsessionsWereActive= False;
2885 MediaSubsessionIterator iter(*session);
2886 MediaSubsession* subsession;
2888 while((subsession= iter.next())!= NULL) {
2889 if(subsession->sink!= NULL) {
2890 RTCPInstance* rtcpInstance;
2891 Medium::close(subsession->sink);
2892 subsession->sink= NULL;
2895 if((rtcpInstance= subsession->rtcpInstance())!= NULL)
2896 rtcpInstance->setByeHandler(NULL, NULL);
2897 someSubsessionsWereActive= True;
2904 if(someSubsessionsWereActive)
2905 rtspClient->sendTeardownCommand(*session, NULL);
2912 LOGW(
"[URL: '%s'] Closing the stream.\n", rtspClient->url());
2913 if(rtspClient->url()!= NULL)
2914 Medium::close(rtspClient);
2918 char const* rtspURL,
volatile int *ref_flag_exit,
2920 char const* applicationName,
2921 portNumBits tunnelOverHTTPPortNum,
log_ctx_t *log_ctx)
2924 verbosityLevel, applicationName, tunnelOverHTTPPortNum, log_ctx);
2927 SimpleRTSPClient::SimpleRTSPClient(UsageEnvironment& env,
char const* rtspURL,
2928 volatile int *ref_flag_exit,
fifo_ctx_t *fifo_ctx,
int verbosityLevel,
2929 char const* applicationName, portNumBits tunnelOverHTTPPortNum,
2931 RTSPClient(env,rtspURL, verbosityLevel, applicationName,
2932 tunnelOverHTTPPortNum, -1),
2933 m_ref_flag_exit(ref_flag_exit),
2935 m_fifo_ctx(fifo_ctx)
2937 LOG_CTX_INIT(m_log_ctx);
2941 SimpleRTSPClient::~SimpleRTSPClient()
2944 SimpleClientMediaSubsession::SimpleClientMediaSubsession(MediaSession& parent):
2945 MediaSubsession(parent)
2949 Boolean SimpleClientMediaSubsession::createSourceObjects(
2950 int useSpecialRTPoffset)
2952 Boolean doNormalMBitRule= False;
2953 char mimeType[strlen(mediumName())+ strlen(codecName())+ 2];
2954 snprintf(mimeType,
sizeof(mimeType),
"%s/%s", mediumName(), codecName());
2956 fReadSource= fRTPSource= SimpleRTPSource::createNew(env(), fRTPSocket,
2957 fRTPPayloadFormat, fRTPTimestampFrequency, mimeType,
2958 (
unsigned)useSpecialRTPoffset, doNormalMBitRule);
2963 char const* sdpDescription)
2966 if (newSession != NULL) {
2967 if (!newSession->initializeWithSDP(sdpDescription)) {
2975 SimpleClientSession::SimpleClientSession(UsageEnvironment& env):
2980 MediaSubsession* SimpleClientSession::createNewMediaSubsession()
2985 StreamClientState::StreamClientState(): iter(NULL), session(NULL),
2986 subsession(NULL), streamTimerTask(NULL), duration(0.0)
2989 StreamClientState::~StreamClientState()
2992 if(session!= NULL) {
2994 session->envir().taskScheduler().unscheduleDelayedTask(streamTimerTask);
2995 Medium::close(session);
3000 MediaSubsession& subsession,
fifo_ctx_t *fifo_ctx,
3001 char const* streamId,
log_ctx_t *log_ctx)
3003 return new DummySink(env, subsession, fifo_ctx, streamId, log_ctx);
3006 DummySink::DummySink(UsageEnvironment& env, MediaSubsession& subsession,
3009 fSubsession(subsession),
3011 m_fifo_ctx(fifo_ctx),
3012 m_proc_frame_ctx(NULL)
3014 LOG_CTX_INIT(m_log_ctx);
3015 fStreamId= strDup(streamId);
3016 fReceiveBuffer=
new u_int8_t[SINK_BUFFER_SIZE];
3017 ASSERT(m_fifo_ctx!= NULL);
3020 DummySink::~DummySink() {
3021 LOGD_CTX_INIT(m_log_ctx); LOGD(
">>%s\n", __FUNCTION__);
3022 m_dummySink_io_mutex.lock();
3023 if(fReceiveBuffer!= NULL)
3024 delete[] fReceiveBuffer;
3025 if(fStreamId!= NULL)
3028 m_dummySink_io_mutex.unlock();
3029 LOGD(
"<<%s\n", __FUNCTION__);
3032 void DummySink::afterGettingFrame(
void* clientData,
unsigned frameSize,
3033 unsigned numTruncatedBytes,
struct timeval presentationTime,
3034 unsigned durationInMicroseconds)
3042 sink->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime,
3043 durationInMicroseconds);
3046 void DummySink::afterGettingFrame(
unsigned frameSize,
3047 unsigned numTruncatedBytes,
struct timeval presentationTime,
3050 register size_t accumu_size, new_size, new_size_alig;
3051 int ret_code, m_bit= -1;
3052 RTPSource *rtpsrc= NULL;
3053 uint8_t *data= NULL;
3054 LOG_CTX_INIT(m_log_ctx);
3055 LOGD(
">>%s (frameSize: %d; numTruncatedBytes: %d)\n", __FUNCTION__,
3056 (
int)frameSize, (
int)numTruncatedBytes);
3063 rtpsrc= fSubsession.rtpSource();
3065 m_bit= rtpsrc->curPacketMarkerBit();
3067 LOGD(
"%s/%s\n", fSubsession.mediumName(),
3068 fSubsession.codecName());
3071 if(m_proc_frame_ctx== NULL) {
3073 CHECK_DO(m_proc_frame_ctx!= NULL,
goto end);
3079 accumu_size= m_proc_frame_ctx->width[0];
3080 new_size= accumu_size+ frameSize;
3085 if(accumu_size> 0 && m_proc_frame_ctx->data!= NULL)
3086 memcpy(data, m_proc_frame_ctx->data, accumu_size);
3087 memcpy(&data[accumu_size], fReceiveBuffer, frameSize);
3088 if(m_proc_frame_ctx->data!= NULL)
3089 free(m_proc_frame_ctx->data);
3090 m_proc_frame_ctx->data= data;
3091 m_proc_frame_ctx->p_data[0]= data;
3093 m_proc_frame_ctx->linesize[0]= new_size_alig;
3094 m_proc_frame_ctx->width[0]= new_size;
3095 m_proc_frame_ctx->height[0]= 1;
3097 m_proc_frame_ctx->pts= 0;
3103 m_proc_frame_ctx->es_id= fSubsession.clientPortNum();
3106 ret_code=
fifo_put(m_fifo_ctx, (
void**)&m_proc_frame_ctx,
3108 if(ret_code== STAT_ENOMEM) {
3113 ASSERT(ret_code== STAT_SUCCESS && m_proc_frame_ctx== NULL);
3115 data= (uint8_t*)realloc(m_proc_frame_ctx->data, new_size);
3117 memcpy(&data[accumu_size], fReceiveBuffer, frameSize);
3118 m_proc_frame_ctx->data= data;
3120 m_proc_frame_ctx->width[0]= new_size;
3128 LOGD(
"<<%s\n", __FUNCTION__);
3132 Boolean DummySink::continuePlaying()
3140 fSource->getNextFrame(fReceiveBuffer, SINK_BUFFER_SIZE, afterGettingFrame,
3141 this, onSourceClosure,
this);
3145 void live555_rtsp_reset_on_new_settings(
proc_ctx_t *proc_ctx,
3148 int ret_code, flag_io_locked= 0, flag_thr_joined= 0;
3149 void *thread_end_code= NULL;
3150 LOG_CTX_INIT(log_ctx);
3175 pthread_join(proc_ctx->
proc_thread, &thread_end_code);
3176 if(thread_end_code!= NULL) {
3177 ASSERT(*((
int*)thread_end_code)== STAT_SUCCESS);
3178 free(thread_end_code);
3179 thread_end_code= NULL;
3189 if(flag_is_muxer!= 0) {
3190 live555_rtsp_reset_on_new_settings_es_mux(proc_ctx, LOG_CTX_GET());
3192 live555_rtsp_reset_on_new_settings_es_dmux(proc_ctx, LOG_CTX_GET());
3201 if(flag_thr_joined!= 0) {
3203 ret_code= pthread_create(&proc_ctx->
proc_thread, NULL,
3209 if(flag_io_locked!= 0) {
3216 void live555_rtsp_reset_on_new_settings_es_mux(
proc_ctx_t *proc_ctx,
3220 int i, ret_code, procs_num= 0;
3226 cJSON *cjson_es_array= NULL, *cjson_aux= NULL;
3227 char *rest_str= NULL;
3228 LOG_CTX_INIT(log_ctx);
3236 live555_rtsp_mux_settings_ctx=
3238 muxers_settings_mux_ctx=
3242 ret_code= live555_rtsp_mux_rest_get_es_array(
3244 &cjson_es_array, LOG_CTX_GET());
3245 CHECK_DO(ret_code== STAT_SUCCESS && cjson_es_array!= NULL,
goto end);
3254 ret_code= live555_rtsp_mux_init_given_settings(live555_rtsp_mux_ctx,
3257 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
3260 procs_num= cJSON_GetArraySize(cjson_es_array);
3261 for(i= 0; i< procs_num; i++) {
3262 char settings_str[128]= {0};
3263 cJSON *cjson_proc= cJSON_GetArrayItem(cjson_es_array, i);
3264 CHECK_DO(cjson_proc!= NULL,
continue);
3266 cjson_aux= cJSON_GetObjectItem(cjson_proc,
"sdp_mimetype");
3267 CHECK_DO(cjson_aux!= NULL,
continue);
3268 sdp_mimetype= cjson_aux->valuestring;
3271 if(rest_str!= NULL) {
3275 snprintf(settings_str,
sizeof(settings_str),
"sdp_mimetype=%s",
3279 procs_ctx_es_muxers,
"PROCS_POST",
3280 "live555_rtsp_es_mux", settings_str, &rest_str,
3283 CHECK_DO(ret_code== STAT_SUCCESS && rest_str!= NULL,
continue);
3287 if(cjson_es_array!= NULL)
3288 cJSON_Delete(cjson_es_array);
3294 void live555_rtsp_reset_on_new_settings_es_dmux(
proc_ctx_t *proc_ctx,
3303 LOG_CTX_INIT(log_ctx);
3311 live555_rtsp_dmux_settings_ctx=
3313 muxers_settings_dmux_ctx=
3319 live555_rtsp_dmux_deinit_except_settings(live555_rtsp_dmux_ctx,
3323 ret_code= live555_rtsp_dmux_init_given_settings(live555_rtsp_dmux_ctx,
3326 ASSERT(ret_code== STAT_SUCCESS);
static int live555_rtsp_dmux_rest_get(proc_ctx_t *proc_ctx, const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
static int live555_rtsp_dmux_rest_put(proc_ctx_t *proc_ctx, const char *str)
void fifo_close(fifo_ctx_t **ref_fifo_ctx)
struct live555_rtsp_es_mux_settings_ctx_s live555_rtsp_es_mux_settings_ctx_t
int fifo_get(fifo_ctx_t *fifo_ctx, void **ref_elem, size_t *ref_elem_size)
static void shutdownStream(RTSPClient *rtspClient, int exitCode=1)
#define CJSON_PRINT(CJSON_PTR)
static int live555_rtsp_dmux_settings_ctx_init(volatile live555_rtsp_dmux_settings_ctx_t *live555_rtsp_dmux_settings_ctx, log_ctx_t *log_ctx)
int muxers_settings_mux_ctx_init(volatile muxers_settings_mux_ctx_t *muxers_settings_mux_ctx)
struct live555_rtsp_mux_settings_ctx_s live555_rtsp_mux_settings_ctx_t
UsageEnvironment * usageEnvironment
size_t width[PROC_FRAME_NUM_DATA_POINTERS]
pthread_t taskScheduler_thread
struct muxers_settings_dmux_ctx_s muxers_settings_dmux_ctx
int muxers_settings_dmux_ctx_restful_put(volatile muxers_settings_dmux_ctx_t *muxers_settings_dmux_ctx, const char *str, log_ctx_t *log_ctx)
TaskScheduler * taskScheduler
static int live555_rtsp_mux_settings_ctx_init(volatile live555_rtsp_mux_settings_ctx_t *live555_rtsp_mux_settings_ctx, log_ctx_t *log_ctx)
void proc_frame_ctx_release(proc_frame_ctx_t **ref_proc_frame_ctx)
#define EXTEND_SIZE_TO_MULTIPLE(SIZE, MULTIPLE)
Multiplexers and de-multiplexers generic settings.
ssize_t fifo_get_buffer_level(fifo_ctx_t *fifo_ctx)
struct live555_rtsp_mux_ctx_s live555_rtsp_mux_ctx_t
struct muxers_settings_mux_ctx_s muxers_settings_mux_ctx
UsageEnvironment * usageEnvironment
void fifo_set_blocking_mode(fifo_ctx_t *fifo_ctx, int do_block)
Generic processor module context (see type proc_ctx_t) extension for multiplexers and de-multiplexers...
int procs_opt(procs_ctx_t *procs_ctx, const char *tag,...)
static proc_ctx_t * live555_rtsp_dmux_open(const proc_if_t *proc_if, const char *settings_str, log_ctx_t *log_ctx, va_list arg)
int fifo_put(fifo_ctx_t *fifo_ctx, void **ref_elem, size_t elem_size)
procs_ctx_t * procs_ctx_es_muxers
int procs_module_opt(const char *tag,...)
static void subsessionByeHandler(void *clientData)
void fifo_empty(fifo_ctx_t *fifo_ctx)
int fifo_show(fifo_ctx_t *fifo_ctx, void **ref_elem, size_t *ref_elem_size)
static int live555_rtsp_es_mux_rest_get(proc_ctx_t *proc_ctx, const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
char * rtsp_streaming_session_name
volatile EventTriggerId m_eventTriggerId
void proc_muxer_mux_ctx_deinit(proc_muxer_mux_ctx_t *proc_muxer_mux_ctx, log_ctx_t *log_ctx)
const proc_if_t proc_if_live555_rtsp_mux
pthread_mutex_t api_mutex
const void *(* start_routine)(void *)
static DummySink * createNew(UsageEnvironment &env, MediaSubsession &subsession, fifo_ctx_t *fifo_ctx, char const *streamId=NULL, log_ctx_t *log_ctx=NULL)
#define CHECK_DO(COND, ACTION)
Character string response.
int procs_send_frame(procs_ctx_t *procs_ctx, int proc_id, const proc_frame_ctx_t *proc_frame_ctx)
fifo_ctx_t * fifo_open(size_t slots_max, size_t chunk_size_max, uint32_t flags, const fifo_elem_alloc_fxn_t *fifo_elem_alloc_fxn)
int muxers_settings_dmux_ctx_init(volatile muxers_settings_dmux_ctx_t *muxers_settings_dmux_ctx)
unsigned int rtp_timestamp_freq
proc_frame_ctx_t * proc_frame_ctx_allocate()
enum proc_if_rest_fmt_enum proc_if_rest_fmt_t
const proc_if_t * proc_if
fifo_ctx_t * fifo_ctx_array[PROC_IO_NUM]
SimpleRTSPClient * simpleRTSPClient
volatile struct live555_rtsp_mux_settings_ctx_s live555_rtsp_mux_settings_ctx
static int live555_rtsp_es_mux_process_frame(proc_ctx_t *proc_ctx, fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx)
TaskScheduler * taskScheduler
static int live555_rtsp_mux_opt(proc_ctx_t *proc_ctx, const char *tag, va_list arg)
static int live555_rtsp_mux_rest_get(proc_ctx_t *proc_ctx, const proc_if_rest_fmt_t rest_fmt, void **ref_reponse)
Live555 based RTSP multiplexer and de-multiplexer wrappers.
ServerMediaSession * serverMediaSession
static void live555_rtsp_dmux_close(proc_ctx_t **ref_proc_ctx)
static int live555_rtsp_es_mux_rest_put(proc_ctx_t *proc_ctx, const char *str)
static void setupNextSubsession(RTSPClient *rtspClient)
volatile struct live555_rtsp_dmux_settings_ctx_s live555_rtsp_dmux_settings_ctx
const proc_if_t proc_if_live555_rtsp_dmux
static int live555_rtsp_mux_rest_put(proc_ctx_t *proc_ctx, const char *str)
static void subsessionAfterPlaying(void *clientData)
proc_frame_ctx_t * proc_frame_ctx_dup(const proc_frame_ctx_t *proc_frame_ctx_arg)
int muxers_settings_mux_ctx_restful_get(volatile muxers_settings_mux_ctx_t *muxers_settings_mux_ctx, cJSON **ref_cjson_rest, log_ctx_t *log_ctx)
TaskScheduler * taskScheduler
static void live555_rtsp_mux_settings_ctx_deinit(volatile live555_rtsp_mux_settings_ctx_t *live555_rtsp_mux_settings_ctx, log_ctx_t *log_ctx)
volatile struct live555_rtsp_es_mux_settings_ctx_s live555_rtsp_es_mux_settings_ctx
void procs_close(procs_ctx_t **ref_procs_ctx)
struct proc_muxer_mux_ctx_s proc_muxer_mux_ctx
static void live555_rtsp_mux_close(proc_ctx_t **ref_proc_ctx)
static void live555_rtsp_mux_deinit_except_settings(live555_rtsp_mux_ctx_t *live555_rtsp_mux_ctx, log_ctx_t *log_ctx)
static void live555_rtsp_dmux_settings_ctx_deinit(volatile live555_rtsp_dmux_settings_ctx_t *live555_rtsp_dmux_settings_ctx, log_ctx_t *log_ctx)
static int live555_rtsp_dmux_process_frame(proc_ctx_t *proc_ctx, fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx)
const uint8_t * p_data[PROC_FRAME_NUM_DATA_POINTERS]
static proc_ctx_t * live555_rtsp_mux_open(const proc_if_t *proc_if, const char *settings_str, log_ctx_t *log_ctx, va_list arg)
fair_lock_t * fair_lock_io_array[PROC_IO_NUM]
int proc_muxer_mux_ctx_init(proc_muxer_mux_ctx_t *proc_muxer_mux_ctx, log_ctx_t *log_ctx)
void muxers_settings_mux_ctx_deinit(volatile muxers_settings_mux_ctx_t *muxers_settings_mux_ctx)
SimpleMediaSubsession * simpleMediaSubsession
void muxers_settings_dmux_ctx_deinit(volatile muxers_settings_dmux_ctx_t *muxers_settings_dmux_ctx)
static int live555_rtsp_mux_process_frame(proc_ctx_t *proc_ctx, fifo_ctx_t *iput_fifo_ctx, fifo_ctx_t *oput_fifo_ctx)
static void live555_rtsp_es_mux_close(proc_ctx_t **ref_proc_ctx)
struct live555_rtsp_dmux_settings_ctx_s live555_rtsp_dmux_settings_ctx_t
int muxers_settings_mux_ctx_restful_put(volatile muxers_settings_mux_ctx_t *muxers_settings_mux_ctx, const char *str, log_ctx_t *log_ctx)