00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MPEG1or2VideoRTPSink.hh"
00022 #include "MPEG1or2VideoStreamFramer.hh"
00023
00024 MPEG1or2VideoRTPSink::MPEG1or2VideoRTPSink(UsageEnvironment& env, Groupsock* RTPgs)
00025 : VideoRTPSink(env, RTPgs, 32, 90000, "MPV") {
00026 fPictureState.temporal_reference = 0;
00027 fPictureState.picture_coding_type = fPictureState.vector_code_bits = 0;
00028 }
00029
00030 MPEG1or2VideoRTPSink::~MPEG1or2VideoRTPSink() {
00031 }
00032
00033 MPEG1or2VideoRTPSink*
00034 MPEG1or2VideoRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs) {
00035 return new MPEG1or2VideoRTPSink(env, RTPgs);
00036 }
00037
00038 Boolean MPEG1or2VideoRTPSink::sourceIsCompatibleWithUs(MediaSource& source) {
00039
00040 return source.isMPEG1or2VideoStreamFramer();
00041 }
00042
00043 Boolean MPEG1or2VideoRTPSink::allowFragmentationAfterStart() const {
00044 return True;
00045 }
00046
00047 Boolean MPEG1or2VideoRTPSink
00048 ::frameCanAppearAfterPacketStart(unsigned char const* frameStart,
00049 unsigned numBytesInFrame) const {
00050
00051
00052
00053
00054
00055 if (!fPreviousFrameWasSlice) return True;
00056
00057
00058
00059 return numBytesInFrame >= 4
00060 && frameStart[0] == 0 && frameStart[1] == 0 && frameStart[2] == 1
00061 && frameStart[3] >= 1 && frameStart[3] <= 0xAF;
00062 }
00063
00064 #define VIDEO_SEQUENCE_HEADER_START_CODE 0x000001B3
00065 #define PICTURE_START_CODE 0x00000100
00066
00067 void MPEG1or2VideoRTPSink
00068 ::doSpecialFrameHandling(unsigned fragmentationOffset,
00069 unsigned char* frameStart,
00070 unsigned numBytesInFrame,
00071 struct timeval framePresentationTime,
00072 unsigned numRemainingBytes) {
00073 Boolean thisFrameIsASlice = False;
00074 if (isFirstFrameInPacket()) {
00075 fSequenceHeaderPresent = fPacketBeginsSlice = fPacketEndsSlice = False;
00076 }
00077
00078 if (fragmentationOffset == 0) {
00079
00080 if (numBytesInFrame < 4) return;
00081 unsigned startCode = (frameStart[0]<<24) | (frameStart[1]<<16)
00082 | (frameStart[2]<<8) | frameStart[3];
00083
00084 if (startCode == VIDEO_SEQUENCE_HEADER_START_CODE) {
00085
00086 fSequenceHeaderPresent = True;
00087 } else if (startCode == PICTURE_START_CODE) {
00088
00089
00090
00091 if (numBytesInFrame < 8) return;
00092 unsigned next4Bytes = (frameStart[4]<<24) | (frameStart[5]<<16)
00093 | (frameStart[6]<<8) | frameStart[7];
00094 unsigned char byte8 = numBytesInFrame == 8 ? 0 : frameStart[8];
00095
00096 fPictureState.temporal_reference = (next4Bytes&0xFFC00000)>>(32-10);
00097 fPictureState.picture_coding_type = (next4Bytes&0x00380000)>>(32-(10+3));
00098
00099 unsigned char FBV, BFC, FFV, FFC;
00100 FBV = BFC = FFV = FFC = 0;
00101 switch (fPictureState.picture_coding_type) {
00102 case 3:
00103 FBV = (byte8&0x40)>>6;
00104 BFC = (byte8&0x38)>>3;
00105
00106 case 2:
00107 FFV = (next4Bytes&0x00000004)>>2;
00108 FFC = ((next4Bytes&0x00000003)<<1) | ((byte8&0x80)>>7);
00109 }
00110
00111 fPictureState.vector_code_bits = (FBV<<7) | (BFC<<4) | (FFV<<3) | FFC;
00112 } else if ((startCode&0xFFFFFF00) == 0x00000100) {
00113 unsigned char lastCodeByte = startCode&0xFF;
00114
00115 if (lastCodeByte <= 0xAF) {
00116
00117 thisFrameIsASlice = True;
00118 } else {
00119
00120 }
00121 } else {
00122
00123 envir() << "Warning: MPEG1or2VideoRTPSink::doSpecialFrameHandling saw strange first 4 bytes "
00124 << (void*)startCode << ", but we're not a fragment\n";
00125 }
00126 } else {
00127
00128 thisFrameIsASlice = True;
00129 }
00130
00131 if (thisFrameIsASlice) {
00132
00133 fPacketBeginsSlice = (fragmentationOffset == 0);
00134
00135
00136 fPacketEndsSlice = (numRemainingBytes == 0);
00137 }
00138
00139
00140
00141
00142
00143
00144 unsigned videoSpecificHeader =
00145
00146 (fPictureState.temporal_reference<<16) |
00147
00148 (fSequenceHeaderPresent<<13) |
00149 (fPacketBeginsSlice<<12) |
00150 (fPacketEndsSlice<<11) |
00151 (fPictureState.picture_coding_type<<8) |
00152 fPictureState.vector_code_bits;
00153 setSpecialHeaderWord(videoSpecificHeader);
00154
00155
00156
00157 setTimestamp(framePresentationTime);
00158
00159
00160
00161
00162 MPEG1or2VideoStreamFramer* framerSource = (MPEG1or2VideoStreamFramer*)fSource;
00163 if (framerSource != NULL && framerSource->pictureEndMarker()
00164 && numRemainingBytes == 0) {
00165 setMarkerBit();
00166 framerSource->pictureEndMarker() = False;
00167 }
00168
00169 fPreviousFrameWasSlice = thisFrameIsASlice;
00170 }
00171
00172 unsigned MPEG1or2VideoRTPSink::specialHeaderSize() const {
00173
00174 return 4;
00175 }