00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MPEG4ESVideoRTPSink.hh"
00022 #include "MPEG4VideoStreamFramer.hh"
00023 #include "MPEG4LATMAudioRTPSource.hh"
00024
00025 MPEG4ESVideoRTPSink
00026 ::MPEG4ESVideoRTPSink(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat, u_int32_t rtpTimestampFrequency,
00027 u_int8_t profileAndLevelIndication, char const* configStr)
00028 : VideoRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, "MP4V-ES"),
00029 fVOPIsPresent(False), fProfileAndLevelIndication(profileAndLevelIndication), fFmtpSDPLine(NULL) {
00030 fConfigBytes = parseGeneralConfigStr(configStr, fNumConfigBytes);
00031 }
00032
00033 MPEG4ESVideoRTPSink::~MPEG4ESVideoRTPSink() {
00034 delete[] fFmtpSDPLine;
00035 delete[] fConfigBytes;
00036 }
00037
00038 MPEG4ESVideoRTPSink*
00039 MPEG4ESVideoRTPSink::createNew(UsageEnvironment& env,
00040 Groupsock* RTPgs, unsigned char rtpPayloadFormat,
00041 u_int32_t rtpTimestampFrequency) {
00042 return new MPEG4ESVideoRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency);
00043 }
00044
00045 MPEG4ESVideoRTPSink*
00046 MPEG4ESVideoRTPSink::createNew(UsageEnvironment& env,
00047 Groupsock* RTPgs, unsigned char rtpPayloadFormat, u_int32_t rtpTimestampFrequency,
00048 u_int8_t profileAndLevelIndication, char const* configStr) {
00049 return new MPEG4ESVideoRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, profileAndLevelIndication, configStr);
00050 }
00051
00052 Boolean MPEG4ESVideoRTPSink::sourceIsCompatibleWithUs(MediaSource& source) {
00053
00054 return source.isMPEG4VideoStreamFramer();
00055 }
00056
00057 #define VOP_START_CODE 0x000001B6
00058
00059 void MPEG4ESVideoRTPSink
00060 ::doSpecialFrameHandling(unsigned fragmentationOffset,
00061 unsigned char* frameStart,
00062 unsigned numBytesInFrame,
00063 struct timeval framePresentationTime,
00064 unsigned numRemainingBytes) {
00065 if (fragmentationOffset == 0) {
00066
00067 if (numBytesInFrame < 4) return;
00068 unsigned startCode = (frameStart[0]<<24) | (frameStart[1]<<16)
00069 | (frameStart[2]<<8) | frameStart[3];
00070
00071 fVOPIsPresent = startCode == VOP_START_CODE;
00072 }
00073
00074
00075
00076
00077 MPEG4VideoStreamFramer* framerSource = (MPEG4VideoStreamFramer*)fSource;
00078 if (framerSource != NULL && framerSource->pictureEndMarker()
00079 && numRemainingBytes == 0) {
00080 setMarkerBit();
00081 framerSource->pictureEndMarker() = False;
00082 }
00083
00084
00085
00086
00087 setTimestamp(framePresentationTime);
00088 }
00089
00090 Boolean MPEG4ESVideoRTPSink::allowFragmentationAfterStart() const {
00091 return True;
00092 }
00093
00094 Boolean MPEG4ESVideoRTPSink
00095 ::frameCanAppearAfterPacketStart(unsigned char const* ,
00096 unsigned ) const {
00097
00098
00099 return !fVOPIsPresent;
00100 }
00101
00102 char const* MPEG4ESVideoRTPSink::auxSDPLine() {
00103
00104
00105
00106 unsigned configLength = fNumConfigBytes;
00107 unsigned char* config = fConfigBytes;
00108 if (fProfileAndLevelIndication == 0 || config == NULL) {
00109
00110 MPEG4VideoStreamFramer* framerSource = (MPEG4VideoStreamFramer*)fSource;
00111 if (framerSource == NULL) return NULL;
00112
00113 fProfileAndLevelIndication = framerSource->profile_and_level_indication();
00114 if (fProfileAndLevelIndication == 0) return NULL;
00115
00116 config = framerSource->getConfigBytes(configLength);
00117 if (config == NULL) return NULL;
00118 }
00119
00120 char const* fmtpFmt =
00121 "a=fmtp:%d "
00122 "profile-level-id=%d;"
00123 "config=";
00124 unsigned fmtpFmtSize = strlen(fmtpFmt)
00125 + 3
00126 + 3
00127 + 2*configLength
00128 + 2 ;
00129 char* fmtp = new char[fmtpFmtSize];
00130 sprintf(fmtp, fmtpFmt, rtpPayloadType(), fProfileAndLevelIndication);
00131 char* endPtr = &fmtp[strlen(fmtp)];
00132 for (unsigned i = 0; i < configLength; ++i) {
00133 sprintf(endPtr, "%02X", config[i]);
00134 endPtr += 2;
00135 }
00136 sprintf(endPtr, "\r\n");
00137
00138 delete[] fFmtpSDPLine;
00139 fFmtpSDPLine = strDup(fmtp);
00140 delete[] fmtp;
00141 return fFmtpSDPLine;
00142 }