00176 {
00177
00178
00179
00180 assert(stream!=NULL);
00181
char *buffer =
new char[MSG_BUFFER_SIZE];
00182 buffer[0] = 0;
00183
char *next = buffer;
00184
int cnt = 0;
00185
00186
if(groups==NULL)
00187 includeRtxInfo =
false;
00188
00189
#if defined WIN32 && !(defined WINCE)
00190
struct timeb tv;
00191 ftime(&tv);
00192 cnt =
00193 sprintf(next,
"v=0\r\no=%s %i %i IN IP4 %s\r\ns=%s\r\nu=http:///\r\ne=admin@\r\n",SERVER_ID,
00194 (
int) tv.time, (
int) tv.millitm, localAddr, filename);
00195
#else
00196
timeval tv;
00197 gettimeofday(&tv, 0);
00198 cnt =
00199 sprintf(next,
"v=0\r\no=%s %i %i IN IP4 %s\r\ns=%s\r\nu=http:///\r\ne=admin@\r\n",SERVER_ID,
00200 (
int) tv.tv_sec, (
int) tv.tv_usec, localAddr, filename);
00201
#endif
00202
00203 next += cnt;
00204 list <ESInfo*> * es = stream->
getESList();
00205 list < ESInfo * >::const_iterator li = es->begin();
00206
float duration = 0;
00207 u32 bitRateInKilobits = 0;
00208
00209
while (li != es->end()) {
00210
if (duration < ((
float) (*li)->getDurationInMs() / 1000.0)) {
00211 duration = ((
float) (*li)->getDurationInMs() / 1000.0);
00212 }
00213
if ((*li)->isAudioStream() || (*li)->isVisualStream()) {
00214
00215 bitRateInKilobits += ((*li)->getAvgBandwidth() / 1024);
00216 }
00217 ++li;
00218 }
00219
if(tc) {
00220 u32 bw = tc->
getNetworkCapacityInByte()*8;
00221
if(bw==0)
00222 bw = tc->
getMaxDecoderBitRateInBit();
00223
else if(tc->
getMaxDecoderBitRateInBit() &&
00224 tc->
getMaxDecoderBitRateInBit() < bw) {
00225 bw = tc->
getMaxDecoderBitRateInBit();
00226 }
00227
if((bw/1024)<bitRateInKilobits)
00228 bitRateInKilobits=bw;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 cnt = sprintf(next,
"c=IN IP4 %s\r\nb=AS:%i\r\nt=0 0\r\n", localAddr,
00241 bitRateInKilobits);
00242
00243 next += cnt;
00244
00245
char *iodstr =
new char[MAX_IOD_SIZE];
00246 iodstr[0] = 0;
00247 u32 iodHandleSize=0;
00248
00249
#ifndef WINCE
00250
int iodenclen = base64encode(stream->
getIODHandle(iodHandleSize), iodHandleSize,
00251 (
unsigned char*)iodstr, MAX_IOD_SIZE);
00252
#else
00253
int iodenclen = 0;
00254
#endif
00255
00256
if(iodenclen<0 || iodenclen>=MAX_IOD_SIZE)
00257 iodenclen=0;
00258 iodstr[iodenclen] = 0;
00259
int streamcnt = es->size();
00260
00261 li = es->begin();
00262 cnt = sprintf(next,
"a=control:*\r\na=mpeg4-iod:\"data:application/mpeg4-iod;base64,%s\"\r\n",
00263 iodstr);
00264 next += cnt;
00265
00266
00267 cnt = sprintf(next,
"a=isma-compliance:1,1.0,1\r\na=range:npt=0-%5.5f\r\n",
00268 duration);
00269 next += cnt;
00270
00271
if(includeRtxInfo && !es->empty()) {
00272
00273 list < ESInfo*>::const_iterator ei=es->begin();
00274 u32 lastMid=1;
00275
while(ei!=es->end()) {
00276
if((*ei)->isAudioStream() ||
00277 (*ei)->isVisualStream() ) {
00278 rtx_group* group=stream->
getRtxGroup( (*ei)->getStreamId(),groups);
00279
if(!group) {
00280
00281 group=
new rtx_group(NACK,3000);
00282 group->midESInfo=lastMid++;
00283 group->rtx->mId=lastMid++;
00284 group->es=(*ei);
00285 group->rtx->ticks=(*ei)->getMediaTimeScale();
00286 groups->push_back(group);
00287 }
00288
if(!group->rtx) {
00289 group->rtx=
new rtx_info(NACK,3000);
00290 group->midESInfo=lastMid++;
00291 group->rtx->mId=lastMid++;
00292 group->es=(*ei);
00293 group->rtx->ticks=(*ei)->getMediaTimeScale();
00294 }
00295 cnt=sprintf(next,
"a=group:FID %u %u\r\n",
00296 group->midESInfo,
00297 group->rtx->mId);
00298 next+=cnt;
00299 }
00300 ++ei;
00301 }
00302
00303 }
00304
int payloadType = SL_PAYLOAD_TYPE;
00305 u32 bw2=0;
00306
00307
for (
int i = 1; i <= streamcnt; i++) {
00308
00309 u32 tid = (*li)->getStreamId();
00310 u32 handlerType = (*li)->getHandlerType();
00311
00312
00313
00314
00315 u32 sze = 0;
00316 u8 volHeader[4096];
00317 u8* newHeader=NULL;
00318 u8* src=NULL;
00319 uint width = 0, height = 0;uint bitrate=0;
00320
00321
if (
'/' == *filename)
00322 filename++;
00323 rtx_group* currentRtx=NULL;
00324
if(includeRtxInfo)
00325 currentRtx=stream->
getRtxGroup(tid,groups);
00326
00327
switch (handlerType) {
00328
case MP4VisualHandlerType:
00329 width = ((VideoESInfo*)(*li))->getWidth();
00330 height = ((VideoESInfo*)(*li))->getHeight();
00331 bitrate=((VideoESInfo*)(*li))->getAvgBandwidth();
00332
if(tc && !perfectHit) {
00333
00334
if(tc->
getDisplayHeight()!=0 &&
00335 tc->
getDisplayHeight() < height)
00336 height=tc->
getDisplayHeight();
00337
if(tc->
getDisplayWidth()!=0 &&
00338 tc->
getDisplayWidth() < width)
00339 width=tc->
getDisplayWidth();
00340 bw2=tc->
getNetworkCapacityInByte()*8;
00341
if(bw2==0)
00342 bw2=tc->
getMaxDecoderBitRateInBit();
00343
else if(tc->
getMaxDecoderBitRateInBit() &&
00344 tc->
getMaxDecoderBitRateInBit() < bw2) {
00345 bw2=tc->
getMaxDecoderBitRateInBit();
00346 }
00347 u32 new_bitrate = width * height * 6;
00348
if (new_bitrate > bw2)
00349 new_bitrate = bw2;
00350
if (new_bitrate < bitrate)
00351 bitrate = new_bitrate;
00352 newHeader = MP4Encoder::createNewHeader((VideoESInfo*)(*li), new_bitrate,
00353 width, height, 300, (
int)((VideoESInfo*)(*li))->getFPS(), &sze);
00354 }
00355
if(!newHeader) {
00356 sze = (*li)->getHeaders(&src);
00357
SDP::encodeDecoderConfig(volHeader, src, sze);
00358 }
00359
else {
00360
SDP::encodeDecoderConfig(volHeader,newHeader,sze);
00361
delete newHeader;newHeader=NULL;
00362 }
00363 cnt = sprintf(next,
"m=video 0 RTP/AVP %i\r\nb=AS:%i\r\n"
00364
"a=rtpmap:%i MP4V-ES/%i\r\n"
00365
"a=control:trackID=%i\r\n"
00366
"a=cliprect:0,0,%i,%i\r\n"
00367
"a=fmtp:%i profile-level-id=1;config=%s\r\n"
00368
00369
"a=mpeg4-esid:%i\r\n"
00370
"a=aspect-ratio=%6.6f\r\n"
00371
"a=frame-pattern=%s\r\n"
00372
"a=bframesamount=%f\r\n",
00373 payloadType, (bitrate / 1024),
00374 payloadType, (*li)->getMediaTimeScale(),
00375 tid,
00376 width, height,
00377 SL_PAYLOAD_TYPE, volHeader,
00378
00379 tid,
00380 ((VideoESInfo*)(*li))->getAspectRatio(),
00381 (((VideoESInfo*)(*li))->hasStaticFramePattern()?
"static":
"dynamic"),
00382 ((VideoESInfo*)(*li))->getAvgBFrameSize());
00383 next += cnt;
00384
00385
if(((VideoESInfo*)(*li))->hasStaticFramePattern()) {
00386 cnt = sprintf(next,
"a=num-bframes %i\r\n"
00387
"a=gop-size %i\r\n",
00388 ((VideoESInfo*)(*li))->getNum_B_frames(),
00389 ((VideoESInfo*)(*li))->getGOP_size());
00390 next+=cnt;
00391 }
00392 payloadType++;
00393
00394
if( includeRtxInfo && currentRtx &&
00395 currentRtx->rtx && currentRtx->rtx->state!=NONE) {
00396 u32 maxRtxDelay=3000;
00397
if( currentRtx->rtx &&
00398 currentRtx->rtx->rtxTimeInMs>0)
00399 maxRtxDelay=currentRtx->rtx->rtxTimeInMs;
00400
else {
00401 currentRtx->rtx=
new rtx_info(NACK,maxRtxDelay);
00402 }
00403
00404
00405 cnt = sprintf(next,
00406
"a=rtcp-fb:%i %s\r\n"
00407
"a=mid:%u\r\n"
00408
"m=video 0 RTP/AVPF %i\r\n"
00409
"a=rtpmap:%i rtx/%u\r\n"
00410
"a=fmtp:%i apt=%i;rtx-time=%u\r\n"
00411
"a=mid:%u\r\n",
00412 payloadType-1, sRTXState[currentRtx->rtx->state],
00413 currentRtx->midESInfo,
00414 payloadType,
00415 payloadType, currentRtx->rtx->ticks,
00416 payloadType,(payloadType-1),maxRtxDelay,
00417 currentRtx->rtx->mId);
00418 next += cnt;
00419 currentRtx->rtx->payloadType=payloadType;
00420 payloadType++;
00421 }
00422
break;
00423
case MP4AudioHandlerType:
00424
00425
if(!tc || (tc && tc->
getNumAudioChannels()>0)) {
00426
00427 u8 decoderConfig[4096];
00428 src = NULL;
00429 payloadType=14;
00430 sze = (*li)->getHeaders(&src);
00431
SDP::encodeDecoderConfig(decoderConfig, src, sze);
00432 cnt = sprintf(next,
"m=audio 0 RTP/AVP %i\r\nb=AS:%i\r\n"
00433
"a=control:trackID=%i\r\n"
00434
"a=mpeg4-esid:%i\r\n"
00435
"a=fmtp:%i DTSDeltaLength=%i; config=%s\r\n"
00436
"a=rtpmap:%i MPA/%i\r\n",
00437 payloadType,((*li)->getAvgBandwidth() / 1024), tid, tid,
00438 payloadType, dtsDeltaLength, decoderConfig,
00439 payloadType, (*li)->getMediaTimeScale());
00440 next += cnt;
00441 payloadType++;
00442
00443
if(includeRtxInfo) {
00444 u32 maxRtxDelay=3000;
00445
if( currentRtx->rtx &&
00446 currentRtx->rtx->rtxTimeInMs>0)
00447 maxRtxDelay=currentRtx->rtx->rtxTimeInMs;
00448
else {
00449 currentRtx->rtx=
new rtx_info(NACK,maxRtxDelay);
00450 }
00451 cnt = sprintf(next,
00452
"a=mid:%ui\r\n"
00453
"m=audio 0 RTP/AVPF %i\r\n"
00454
"a=rtpmap:%i rtx/%i\r\n"
00455
"a=fmtp:%i apt=%i;rtx-time=%ui\r\n"
00456
"a=mid:%i\r\n",
00457 currentRtx->midESInfo,
00458 payloadType,
00459 payloadType, currentRtx->rtx->ticks,
00460 payloadType,(payloadType-1),maxRtxDelay,
00461 currentRtx->rtx->mId);
00462 next += cnt;
00463 currentRtx->rtx->payloadType=payloadType;
00464 payloadType++;
00465 }
00466 }
00467
break;
00468
default:
00469
00470
00471
00472
00473
00474
00475
00476 ;
00477 }
00478 ++li;
00479
if(src)
00480
delete src;
00481 }
00482
00483 *next = 0;
00484
char *result =
new char[strlen(buffer) + 1];
00485 strcpy(result, buffer);
00486
00487
delete [] iodstr;
00488
delete [] buffer;
00489
return result;
00490 };