1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "rtp_test" 19 #include <utils/Log.h> 20 21 #include <binder/ProcessState.h> 22 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/foundation/ALooper.h> 25 #include <media/stagefright/DataSource.h> 26 #include <media/stagefright/MetaData.h> 27 #include <media/stagefright/OMXClient.h> 28 #include <media/stagefright/OMXCodec.h> 29 #include <media/stagefright/foundation/base64.h> 30 31 #include "ARTPSession.h" 32 #include "ASessionDescription.h" 33 #include "UDPPusher.h" 34 35 using namespace android; 36 37 int main(int argc, char **argv) { 38 android::ProcessState::self()->startThreadPool(); 39 40 DataSource::RegisterDefaultSniffers(); 41 42 const char *rtpFilename = NULL; 43 const char *rtcpFilename = NULL; 44 45 if (argc == 3) { 46 rtpFilename = argv[1]; 47 rtcpFilename = argv[2]; 48 } else if (argc != 1) { 49 fprintf(stderr, "usage: %s [ rtpFilename rtcpFilename ]\n", argv[0]); 50 return 1; 51 } 52 53 #if 0 54 static const uint8_t kSPS[] = { 55 0x67, 0x42, 0x80, 0x0a, 0xe9, 0x02, 0x83, 0xe4, 0x20, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x0e, 0xa6, 0x00, 0x80 56 }; 57 static const uint8_t kPPS[] = { 58 0x68, 0xce, 0x3c, 0x80 59 }; 60 AString out1, out2; 61 encodeBase64(kSPS, sizeof(kSPS), &out1); 62 encodeBase64(kPPS, sizeof(kPPS), &out2); 63 printf("params=%s,%s\n", out1.c_str(), out2.c_str()); 64 #endif 65 66 sp<ALooper> looper = new ALooper; 67 68 sp<UDPPusher> rtp_pusher; 69 sp<UDPPusher> rtcp_pusher; 70 71 if (rtpFilename != NULL) { 72 rtp_pusher = new UDPPusher(rtpFilename, 5434); 73 looper->registerHandler(rtp_pusher); 74 75 rtcp_pusher = new UDPPusher(rtcpFilename, 5435); 76 looper->registerHandler(rtcp_pusher); 77 } 78 79 sp<ARTPSession> session = new ARTPSession; 80 looper->registerHandler(session); 81 82 #if 0 83 // My H264 SDP 84 static const char *raw = 85 "v=0\r\n" 86 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 87 "s=QuickTime\r\n" 88 "t=0 0\r\n" 89 "a=range:npt=0-315\r\n" 90 "a=isma-compliance:2,2.0,2\r\n" 91 "m=video 5434 RTP/AVP 97\r\n" 92 "c=IN IP4 127.0.0.1\r\n" 93 "b=AS:30\r\n" 94 "a=rtpmap:97 H264/90000\r\n" 95 "a=fmtp:97 packetization-mode=1;profile-level-id=42000C;" 96 "sprop-parameter-sets=Z0IADJZUCg+I,aM44gA==\r\n" 97 "a=mpeg4-esid:201\r\n" 98 "a=cliprect:0,0,240,320\r\n" 99 "a=framesize:97 320-240\r\n"; 100 #elif 0 101 // My H263 SDP 102 static const char *raw = 103 "v=0\r\n" 104 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 105 "s=QuickTime\r\n" 106 "t=0 0\r\n" 107 "a=range:npt=0-315\r\n" 108 "a=isma-compliance:2,2.0,2\r\n" 109 "m=video 5434 RTP/AVP 97\r\n" 110 "c=IN IP4 127.0.0.1\r\n" 111 "b=AS:30\r\n" 112 "a=rtpmap:97 H263-1998/90000\r\n" 113 "a=cliprect:0,0,240,320\r\n" 114 "a=framesize:97 320-240\r\n"; 115 #elif 0 116 // My AMR SDP 117 static const char *raw = 118 "v=0\r\n" 119 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 120 "s=QuickTime\r\n" 121 "t=0 0\r\n" 122 "a=range:npt=0-315\r\n" 123 "a=isma-compliance:2,2.0,2\r\n" 124 "m=audio 5434 RTP/AVP 97\r\n" 125 "c=IN IP4 127.0.0.1\r\n" 126 "b=AS:30\r\n" 127 "a=rtpmap:97 AMR/8000/1\r\n" 128 "a=fmtp:97 octet-align\r\n"; 129 #elif 1 130 // GTalk's H264 SDP 131 static const char *raw = 132 "v=0\r\n" 133 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 134 "s=QuickTime\r\n" 135 "t=0 0\r\n" 136 "a=range:npt=now-\r\n" 137 "m=video 5434 RTP/AVP 96\r\n" 138 "c=IN IP4 127.0.0.1\r\n" 139 "b=AS:320000\r\n" 140 "a=rtpmap:96 H264/90000\r\n" 141 "a=fmtp:96 packetization-mode=1;profile-level-id=42001E;" 142 "sprop-parameter-sets=Z0IAHpZUBaHogA==,aM44gA==\r\n" 143 "a=cliprect:0,0,480,270\r\n" 144 "a=framesize:96 720-480\r\n"; 145 #else 146 // sholes H264 SDP 147 static const char *raw = 148 "v=0\r\n" 149 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 150 "s=QuickTime\r\n" 151 "t=0 0\r\n" 152 "a=range:npt=now-\r\n" 153 "m=video 5434 RTP/AVP 96\r\n" 154 "c=IN IP4 127.0.0.1\r\n" 155 "b=AS:320000\r\n" 156 "a=rtpmap:96 H264/90000\r\n" 157 "a=fmtp:96 packetization-mode=1;profile-level-id=42001E;" 158 "sprop-parameter-sets=Z0KACukCg+QgAAB9AAAOpgCA,aM48gA==\r\n" 159 "a=cliprect:0,0,240,320\r\n" 160 "a=framesize:96 320-240\r\n"; 161 #endif 162 163 sp<ASessionDescription> desc = new ASessionDescription; 164 CHECK(desc->setTo(raw, strlen(raw))); 165 166 CHECK_EQ(session->setup(desc), (status_t)OK); 167 168 if (rtp_pusher != NULL) { 169 rtp_pusher->start(); 170 } 171 172 if (rtcp_pusher != NULL) { 173 rtcp_pusher->start(); 174 } 175 176 looper->start(false /* runOnCallingThread */); 177 178 CHECK_EQ(session->countTracks(), 1u); 179 sp<MediaSource> source = session->trackAt(0); 180 181 OMXClient client; 182 CHECK_EQ(client.connect(), (status_t)OK); 183 184 sp<MediaSource> decoder = OMXCodec::Create( 185 client.interface(), 186 source->getFormat(), false /* createEncoder */, 187 source, 188 NULL, 189 0); // OMXCodec::kPreferSoftwareCodecs); 190 CHECK(decoder != NULL); 191 192 CHECK_EQ(decoder->start(), (status_t)OK); 193 194 for (;;) { 195 MediaBuffer *buffer; 196 status_t err = decoder->read(&buffer); 197 198 if (err != OK) { 199 if (err == INFO_FORMAT_CHANGED) { 200 int32_t width, height; 201 CHECK(decoder->getFormat()->findInt32(kKeyWidth, &width)); 202 CHECK(decoder->getFormat()->findInt32(kKeyHeight, &height)); 203 printf("INFO_FORMAT_CHANGED %d x %d\n", width, height); 204 continue; 205 } 206 207 ALOGE("decoder returned error 0x%08x", err); 208 break; 209 } 210 211 #if 1 212 if (buffer->range_length() != 0) { 213 int64_t timeUs; 214 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 215 216 printf("decoder returned frame of size %d at time %.2f secs\n", 217 buffer->range_length(), timeUs / 1E6); 218 } 219 #endif 220 221 buffer->release(); 222 buffer = NULL; 223 } 224 225 CHECK_EQ(decoder->stop(), (status_t)OK); 226 227 looper->stop(); 228 229 return 0; 230 } 231