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