00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavcodec/bytestream.h"
00028 #include "libavutil/avstring.h"
00029 #include "libavutil/intfloat.h"
00030 #include "libavutil/lfg.h"
00031 #include "libavutil/opt.h"
00032 #include "libavutil/sha.h"
00033 #include "avformat.h"
00034 #include "internal.h"
00035
00036 #include "network.h"
00037
00038 #include "flv.h"
00039 #include "rtmp.h"
00040 #include "rtmppkt.h"
00041 #include "url.h"
00042
00043
00044
00045 #define APP_MAX_LENGTH 128
00046 #define PLAYPATH_MAX_LENGTH 256
00047 #define TCURL_MAX_LENGTH 512
00048 #define FLASHVER_MAX_LENGTH 64
00049
00051 typedef enum {
00052 STATE_START,
00053 STATE_HANDSHAKED,
00054 STATE_RELEASING,
00055 STATE_FCPUBLISH,
00056 STATE_CONNECTING,
00057 STATE_READY,
00058 STATE_PLAYING,
00059 STATE_PUBLISHING,
00060 STATE_STOPPED,
00061 } ClientState;
00062
00064 typedef struct RTMPContext {
00065 const AVClass *class;
00066 URLContext* stream;
00067 RTMPPacket prev_pkt[2][RTMP_CHANNELS];
00068 int chunk_size;
00069 int is_input;
00070 char *playpath;
00071 int live;
00072 char *app;
00073 ClientState state;
00074 int main_channel_id;
00075 uint8_t* flv_data;
00076 int flv_size;
00077 int flv_off;
00078 RTMPPacket out_pkt;
00079 uint32_t client_report_size;
00080 uint32_t bytes_read;
00081 uint32_t last_bytes_read;
00082 int skip_bytes;
00083 uint8_t flv_header[11];
00084 int flv_header_bytes;
00085 int nb_invokes;
00086 int create_stream_invoke;
00087 char* tcurl;
00088 char* flashver;
00089 char* swfurl;
00090 } RTMPContext;
00091
00092 #define PLAYER_KEY_OPEN_PART_LEN 30
00093
00094 static const uint8_t rtmp_player_key[] = {
00095 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
00096 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', '0', '0', '1',
00097
00098 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
00099 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
00100 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
00101 };
00102
00103 #define SERVER_KEY_OPEN_PART_LEN 36
00104
00105 static const uint8_t rtmp_server_key[] = {
00106 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ',
00107 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ',
00108 'S', 'e', 'r', 'v', 'e', 'r', ' ', '0', '0', '1',
00109
00110 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, 0x02,
00111 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, 0x93, 0xB8,
00112 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE
00113 };
00114
00118 static int gen_connect(URLContext *s, RTMPContext *rt)
00119 {
00120 RTMPPacket pkt;
00121 uint8_t *p;
00122 int ret;
00123
00124 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00125 0, 4096)) < 0)
00126 return ret;
00127
00128 p = pkt.data;
00129
00130 ff_amf_write_string(&p, "connect");
00131 ff_amf_write_number(&p, ++rt->nb_invokes);
00132 ff_amf_write_object_start(&p);
00133 ff_amf_write_field_name(&p, "app");
00134 ff_amf_write_string(&p, rt->app);
00135
00136 if (!rt->is_input) {
00137 ff_amf_write_field_name(&p, "type");
00138 ff_amf_write_string(&p, "nonprivate");
00139 }
00140 ff_amf_write_field_name(&p, "flashVer");
00141 ff_amf_write_string(&p, rt->flashver);
00142
00143 if (rt->swfurl) {
00144 ff_amf_write_field_name(&p, "swfUrl");
00145 ff_amf_write_string(&p, rt->swfurl);
00146 }
00147
00148 ff_amf_write_field_name(&p, "tcUrl");
00149 ff_amf_write_string(&p, rt->tcurl);
00150 if (rt->is_input) {
00151 ff_amf_write_field_name(&p, "fpad");
00152 ff_amf_write_bool(&p, 0);
00153 ff_amf_write_field_name(&p, "capabilities");
00154 ff_amf_write_number(&p, 15.0);
00155
00156
00157
00158
00159 ff_amf_write_field_name(&p, "audioCodecs");
00160 ff_amf_write_number(&p, 4071.0);
00161 ff_amf_write_field_name(&p, "videoCodecs");
00162 ff_amf_write_number(&p, 252.0);
00163 ff_amf_write_field_name(&p, "videoFunction");
00164 ff_amf_write_number(&p, 1.0);
00165 }
00166 ff_amf_write_object_end(&p);
00167
00168 pkt.data_size = p - pkt.data;
00169
00170 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00171 ff_rtmp_packet_destroy(&pkt);
00172
00173 return 0;
00174 }
00175
00180 static int gen_release_stream(URLContext *s, RTMPContext *rt)
00181 {
00182 RTMPPacket pkt;
00183 uint8_t *p;
00184 int ret;
00185
00186 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00187 0, 29 + strlen(rt->playpath))) < 0)
00188 return ret;
00189
00190 av_log(s, AV_LOG_DEBUG, "Releasing stream...\n");
00191 p = pkt.data;
00192 ff_amf_write_string(&p, "releaseStream");
00193 ff_amf_write_number(&p, ++rt->nb_invokes);
00194 ff_amf_write_null(&p);
00195 ff_amf_write_string(&p, rt->playpath);
00196
00197 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00198 ff_rtmp_packet_destroy(&pkt);
00199
00200 return 0;
00201 }
00202
00207 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
00208 {
00209 RTMPPacket pkt;
00210 uint8_t *p;
00211 int ret;
00212
00213 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00214 0, 25 + strlen(rt->playpath))) < 0)
00215 return ret;
00216
00217 av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n");
00218 p = pkt.data;
00219 ff_amf_write_string(&p, "FCPublish");
00220 ff_amf_write_number(&p, ++rt->nb_invokes);
00221 ff_amf_write_null(&p);
00222 ff_amf_write_string(&p, rt->playpath);
00223
00224 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00225 ff_rtmp_packet_destroy(&pkt);
00226
00227 return 0;
00228 }
00229
00234 static int gen_fcunpublish_stream(URLContext *s, RTMPContext *rt)
00235 {
00236 RTMPPacket pkt;
00237 uint8_t *p;
00238 int ret;
00239
00240 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00241 0, 27 + strlen(rt->playpath))) < 0)
00242 return ret;
00243
00244 av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n");
00245 p = pkt.data;
00246 ff_amf_write_string(&p, "FCUnpublish");
00247 ff_amf_write_number(&p, ++rt->nb_invokes);
00248 ff_amf_write_null(&p);
00249 ff_amf_write_string(&p, rt->playpath);
00250
00251 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00252 ff_rtmp_packet_destroy(&pkt);
00253
00254 return 0;
00255 }
00256
00261 static int gen_create_stream(URLContext *s, RTMPContext *rt)
00262 {
00263 RTMPPacket pkt;
00264 uint8_t *p;
00265 int ret;
00266
00267 av_log(s, AV_LOG_DEBUG, "Creating stream...\n");
00268
00269 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00270 0, 25)) < 0)
00271 return ret;
00272
00273 p = pkt.data;
00274 ff_amf_write_string(&p, "createStream");
00275 ff_amf_write_number(&p, ++rt->nb_invokes);
00276 ff_amf_write_null(&p);
00277 rt->create_stream_invoke = rt->nb_invokes;
00278
00279 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00280 ff_rtmp_packet_destroy(&pkt);
00281
00282 return 0;
00283 }
00284
00285
00290 static int gen_delete_stream(URLContext *s, RTMPContext *rt)
00291 {
00292 RTMPPacket pkt;
00293 uint8_t *p;
00294 int ret;
00295
00296 av_log(s, AV_LOG_DEBUG, "Deleting stream...\n");
00297
00298 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00299 0, 34)) < 0)
00300 return ret;
00301
00302 p = pkt.data;
00303 ff_amf_write_string(&p, "deleteStream");
00304 ff_amf_write_number(&p, ++rt->nb_invokes);
00305 ff_amf_write_null(&p);
00306 ff_amf_write_number(&p, rt->main_channel_id);
00307
00308 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00309 ff_rtmp_packet_destroy(&pkt);
00310
00311 return 0;
00312 }
00313
00318 static int gen_play(URLContext *s, RTMPContext *rt)
00319 {
00320 RTMPPacket pkt;
00321 uint8_t *p;
00322 int ret;
00323
00324 av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath);
00325
00326 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE,
00327 0, 29 + strlen(rt->playpath))) < 0)
00328 return ret;
00329
00330 pkt.extra = rt->main_channel_id;
00331
00332 p = pkt.data;
00333 ff_amf_write_string(&p, "play");
00334 ff_amf_write_number(&p, ++rt->nb_invokes);
00335 ff_amf_write_null(&p);
00336 ff_amf_write_string(&p, rt->playpath);
00337 ff_amf_write_number(&p, rt->live);
00338
00339 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00340 ff_rtmp_packet_destroy(&pkt);
00341
00342
00343 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
00344 1, 10)) < 0)
00345 return ret;
00346
00347 p = pkt.data;
00348 bytestream_put_be16(&p, 3);
00349 bytestream_put_be32(&p, 1);
00350 bytestream_put_be32(&p, 256);
00351
00352 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00353 ff_rtmp_packet_destroy(&pkt);
00354
00355 return 0;
00356 }
00357
00361 static int gen_publish(URLContext *s, RTMPContext *rt)
00362 {
00363 RTMPPacket pkt;
00364 uint8_t *p;
00365 int ret;
00366
00367 av_log(s, AV_LOG_DEBUG, "Sending publish command for '%s'\n", rt->playpath);
00368
00369 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SOURCE_CHANNEL, RTMP_PT_INVOKE,
00370 0, 30 + strlen(rt->playpath))) < 0)
00371 return ret;
00372
00373 pkt.extra = rt->main_channel_id;
00374
00375 p = pkt.data;
00376 ff_amf_write_string(&p, "publish");
00377 ff_amf_write_number(&p, ++rt->nb_invokes);
00378 ff_amf_write_null(&p);
00379 ff_amf_write_string(&p, rt->playpath);
00380 ff_amf_write_string(&p, "live");
00381
00382 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00383 ff_rtmp_packet_destroy(&pkt);
00384
00385 return ret;
00386 }
00387
00391 static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt)
00392 {
00393 RTMPPacket pkt;
00394 uint8_t *p;
00395 int ret;
00396
00397 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_PING,
00398 ppkt->timestamp + 1, 6)) < 0)
00399 return ret;
00400
00401 p = pkt.data;
00402 bytestream_put_be16(&p, 7);
00403 bytestream_put_be32(&p, AV_RB32(ppkt->data+2));
00404 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00405 ff_rtmp_packet_destroy(&pkt);
00406
00407 return 0;
00408 }
00409
00413 static int gen_server_bw(URLContext *s, RTMPContext *rt)
00414 {
00415 RTMPPacket pkt;
00416 uint8_t *p;
00417 int ret;
00418
00419 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_SERVER_BW,
00420 0, 4)) < 0)
00421 return ret;
00422
00423 p = pkt.data;
00424 bytestream_put_be32(&p, 2500000);
00425 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00426 ff_rtmp_packet_destroy(&pkt);
00427
00428 return 0;
00429 }
00430
00434 static int gen_check_bw(URLContext *s, RTMPContext *rt)
00435 {
00436 RTMPPacket pkt;
00437 uint8_t *p;
00438 int ret;
00439
00440 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE,
00441 0, 21)) < 0)
00442 return ret;
00443
00444 p = pkt.data;
00445 ff_amf_write_string(&p, "_checkbw");
00446 ff_amf_write_number(&p, ++rt->nb_invokes);
00447 ff_amf_write_null(&p);
00448
00449 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00450 ff_rtmp_packet_destroy(&pkt);
00451
00452 return ret;
00453 }
00454
00458 static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
00459 {
00460 RTMPPacket pkt;
00461 uint8_t *p;
00462 int ret;
00463
00464 if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ,
00465 ts, 4)) < 0)
00466 return ret;
00467
00468 p = pkt.data;
00469 bytestream_put_be32(&p, rt->bytes_read);
00470 ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
00471 ff_rtmp_packet_destroy(&pkt);
00472
00473 return 0;
00474 }
00475
00476
00477 #define HMAC_IPAD_VAL 0x36
00478 #define HMAC_OPAD_VAL 0x5C
00479
00491 static int rtmp_calc_digest(const uint8_t *src, int len, int gap,
00492 const uint8_t *key, int keylen, uint8_t *dst)
00493 {
00494 struct AVSHA *sha;
00495 uint8_t hmac_buf[64+32] = {0};
00496 int i;
00497
00498 sha = av_mallocz(av_sha_size);
00499 if (!sha)
00500 return AVERROR(ENOMEM);
00501
00502 if (keylen < 64) {
00503 memcpy(hmac_buf, key, keylen);
00504 } else {
00505 av_sha_init(sha, 256);
00506 av_sha_update(sha,key, keylen);
00507 av_sha_final(sha, hmac_buf);
00508 }
00509 for (i = 0; i < 64; i++)
00510 hmac_buf[i] ^= HMAC_IPAD_VAL;
00511
00512 av_sha_init(sha, 256);
00513 av_sha_update(sha, hmac_buf, 64);
00514 if (gap <= 0) {
00515 av_sha_update(sha, src, len);
00516 } else {
00517 av_sha_update(sha, src, gap);
00518 av_sha_update(sha, src + gap + 32, len - gap - 32);
00519 }
00520 av_sha_final(sha, hmac_buf + 64);
00521
00522 for (i = 0; i < 64; i++)
00523 hmac_buf[i] ^= HMAC_IPAD_VAL ^ HMAC_OPAD_VAL;
00524 av_sha_init(sha, 256);
00525 av_sha_update(sha, hmac_buf, 64+32);
00526 av_sha_final(sha, dst);
00527
00528 av_free(sha);
00529
00530 return 0;
00531 }
00532
00540 static int rtmp_handshake_imprint_with_digest(uint8_t *buf)
00541 {
00542 int i, digest_pos = 0;
00543 int ret;
00544
00545 for (i = 8; i < 12; i++)
00546 digest_pos += buf[i];
00547 digest_pos = (digest_pos % 728) + 12;
00548
00549 ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
00550 rtmp_player_key, PLAYER_KEY_OPEN_PART_LEN,
00551 buf + digest_pos);
00552 if (ret < 0)
00553 return ret;
00554
00555 return digest_pos;
00556 }
00557
00565 static int rtmp_validate_digest(uint8_t *buf, int off)
00566 {
00567 int i, digest_pos = 0;
00568 uint8_t digest[32];
00569 int ret;
00570
00571 for (i = 0; i < 4; i++)
00572 digest_pos += buf[i + off];
00573 digest_pos = (digest_pos % 728) + off + 4;
00574
00575 ret = rtmp_calc_digest(buf, RTMP_HANDSHAKE_PACKET_SIZE, digest_pos,
00576 rtmp_server_key, SERVER_KEY_OPEN_PART_LEN,
00577 digest);
00578 if (ret < 0)
00579 return ret;
00580
00581 if (!memcmp(digest, buf + digest_pos, 32))
00582 return digest_pos;
00583 return 0;
00584 }
00585
00592 static int rtmp_handshake(URLContext *s, RTMPContext *rt)
00593 {
00594 AVLFG rnd;
00595 uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1] = {
00596 3,
00597 0, 0, 0, 0,
00598 RTMP_CLIENT_VER1,
00599 RTMP_CLIENT_VER2,
00600 RTMP_CLIENT_VER3,
00601 RTMP_CLIENT_VER4,
00602 };
00603 uint8_t clientdata[RTMP_HANDSHAKE_PACKET_SIZE];
00604 uint8_t serverdata[RTMP_HANDSHAKE_PACKET_SIZE+1];
00605 int i;
00606 int server_pos, client_pos;
00607 uint8_t digest[32];
00608 int ret;
00609
00610 av_log(s, AV_LOG_DEBUG, "Handshaking...\n");
00611
00612 av_lfg_init(&rnd, 0xDEADC0DE);
00613
00614 for (i = 9; i <= RTMP_HANDSHAKE_PACKET_SIZE; i++)
00615 tosend[i] = av_lfg_get(&rnd) >> 24;
00616 client_pos = rtmp_handshake_imprint_with_digest(tosend + 1);
00617 if (client_pos < 0)
00618 return client_pos;
00619
00620 ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1);
00621 i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1);
00622 if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) {
00623 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
00624 return AVERROR(EIO);
00625 }
00626 i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE);
00627 if (i != RTMP_HANDSHAKE_PACKET_SIZE) {
00628 av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n");
00629 return AVERROR(EIO);
00630 }
00631
00632 av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n",
00633 serverdata[5], serverdata[6], serverdata[7], serverdata[8]);
00634
00635 if (rt->is_input && serverdata[5] >= 3) {
00636 server_pos = rtmp_validate_digest(serverdata + 1, 772);
00637 if (server_pos < 0)
00638 return server_pos;
00639
00640 if (!server_pos) {
00641 server_pos = rtmp_validate_digest(serverdata + 1, 8);
00642 if (server_pos < 0)
00643 return server_pos;
00644
00645 if (!server_pos) {
00646 av_log(s, AV_LOG_ERROR, "Server response validating failed\n");
00647 return AVERROR(EIO);
00648 }
00649 }
00650
00651 ret = rtmp_calc_digest(tosend + 1 + client_pos, 32, 0, rtmp_server_key,
00652 sizeof(rtmp_server_key), digest);
00653 if (ret < 0)
00654 return ret;
00655
00656 ret = rtmp_calc_digest(clientdata, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
00657 digest, 32, digest);
00658 if (ret < 0)
00659 return ret;
00660
00661 if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) {
00662 av_log(s, AV_LOG_ERROR, "Signature mismatch\n");
00663 return AVERROR(EIO);
00664 }
00665
00666 for (i = 0; i < RTMP_HANDSHAKE_PACKET_SIZE; i++)
00667 tosend[i] = av_lfg_get(&rnd) >> 24;
00668 ret = rtmp_calc_digest(serverdata + 1 + server_pos, 32, 0,
00669 rtmp_player_key, sizeof(rtmp_player_key),
00670 digest);
00671 if (ret < 0)
00672 return ret;
00673
00674 ret = rtmp_calc_digest(tosend, RTMP_HANDSHAKE_PACKET_SIZE - 32, 0,
00675 digest, 32,
00676 tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32);
00677 if (ret < 0)
00678 return ret;
00679
00680
00681 ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE);
00682 } else {
00683 ffurl_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE);
00684 }
00685
00686 return 0;
00687 }
00688
00695 static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
00696 {
00697 int i, t;
00698 const uint8_t *data_end = pkt->data + pkt->data_size;
00699 int ret;
00700
00701 #ifdef DEBUG
00702 ff_rtmp_packet_dump(s, pkt);
00703 #endif
00704
00705 switch (pkt->type) {
00706 case RTMP_PT_CHUNK_SIZE:
00707 if (pkt->data_size != 4) {
00708 av_log(s, AV_LOG_ERROR,
00709 "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
00710 return -1;
00711 }
00712 if (!rt->is_input)
00713 ff_rtmp_packet_write(rt->stream, pkt, rt->chunk_size, rt->prev_pkt[1]);
00714 rt->chunk_size = AV_RB32(pkt->data);
00715 if (rt->chunk_size <= 0) {
00716 av_log(s, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
00717 return -1;
00718 }
00719 av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
00720 break;
00721 case RTMP_PT_PING:
00722 t = AV_RB16(pkt->data);
00723 if (t == 6)
00724 if ((ret = gen_pong(s, rt, pkt)) < 0)
00725 return ret;
00726 break;
00727 case RTMP_PT_CLIENT_BW:
00728 if (pkt->data_size < 4) {
00729 av_log(s, AV_LOG_ERROR,
00730 "Client bandwidth report packet is less than 4 bytes long (%d)\n",
00731 pkt->data_size);
00732 return -1;
00733 }
00734 av_log(s, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
00735 rt->client_report_size = AV_RB32(pkt->data) >> 1;
00736 break;
00737 case RTMP_PT_INVOKE:
00738
00739 if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
00740 uint8_t tmpstr[256];
00741
00742 if (!ff_amf_get_field_value(pkt->data + 9, data_end,
00743 "description", tmpstr, sizeof(tmpstr)))
00744 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
00745 return -1;
00746 } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
00747 switch (rt->state) {
00748 case STATE_HANDSHAKED:
00749 if (!rt->is_input) {
00750 if ((ret = gen_release_stream(s, rt)) < 0)
00751 return ret;
00752 if ((ret = gen_fcpublish_stream(s, rt)) < 0)
00753 return ret;
00754 rt->state = STATE_RELEASING;
00755 } else {
00756 if ((ret = gen_server_bw(s, rt)) < 0)
00757 return ret;
00758 rt->state = STATE_CONNECTING;
00759 }
00760 if ((ret = gen_create_stream(s, rt)) < 0)
00761 return ret;
00762 break;
00763 case STATE_FCPUBLISH:
00764 rt->state = STATE_CONNECTING;
00765 break;
00766 case STATE_RELEASING:
00767 rt->state = STATE_FCPUBLISH;
00768
00769
00770 if (!pkt->data[10]) {
00771 int pkt_id = av_int2double(AV_RB64(pkt->data + 11));
00772 if (pkt_id == rt->create_stream_invoke)
00773 rt->state = STATE_CONNECTING;
00774 }
00775 if (rt->state != STATE_CONNECTING)
00776 break;
00777 case STATE_CONNECTING:
00778
00779 if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
00780 av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n");
00781 } else {
00782 rt->main_channel_id = av_int2double(AV_RB64(pkt->data + 21));
00783 }
00784 if (rt->is_input) {
00785 if ((ret = gen_play(s, rt)) < 0)
00786 return ret;
00787 } else {
00788 if ((ret = gen_publish(s, rt)) < 0)
00789 return ret;
00790 }
00791 rt->state = STATE_READY;
00792 break;
00793 }
00794 } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {
00795 const uint8_t* ptr = pkt->data + 11;
00796 uint8_t tmpstr[256];
00797
00798 for (i = 0; i < 2; i++) {
00799 t = ff_amf_tag_size(ptr, data_end);
00800 if (t < 0)
00801 return 1;
00802 ptr += t;
00803 }
00804 t = ff_amf_get_field_value(ptr, data_end,
00805 "level", tmpstr, sizeof(tmpstr));
00806 if (!t && !strcmp(tmpstr, "error")) {
00807 if (!ff_amf_get_field_value(ptr, data_end,
00808 "description", tmpstr, sizeof(tmpstr)))
00809 av_log(s, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
00810 return -1;
00811 }
00812 t = ff_amf_get_field_value(ptr, data_end,
00813 "code", tmpstr, sizeof(tmpstr));
00814 if (!t && !strcmp(tmpstr, "NetStream.Play.Start")) rt->state = STATE_PLAYING;
00815 if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
00816 if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
00817 if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
00818 } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
00819 if ((ret = gen_check_bw(s, rt)) < 0)
00820 return ret;
00821 }
00822 break;
00823 }
00824 return 0;
00825 }
00826
00838 static int get_packet(URLContext *s, int for_header)
00839 {
00840 RTMPContext *rt = s->priv_data;
00841 int ret;
00842 uint8_t *p;
00843 const uint8_t *next;
00844 uint32_t data_size;
00845 uint32_t ts, cts, pts=0;
00846
00847 if (rt->state == STATE_STOPPED)
00848 return AVERROR_EOF;
00849
00850 for (;;) {
00851 RTMPPacket rpkt = { 0 };
00852 if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
00853 rt->chunk_size, rt->prev_pkt[0])) <= 0) {
00854 if (ret == 0) {
00855 return AVERROR(EAGAIN);
00856 } else {
00857 return AVERROR(EIO);
00858 }
00859 }
00860 rt->bytes_read += ret;
00861 if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
00862 av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
00863 if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
00864 return ret;
00865 rt->last_bytes_read = rt->bytes_read;
00866 }
00867
00868 ret = rtmp_parse_result(s, rt, &rpkt);
00869 if (ret < 0) {
00870 ff_rtmp_packet_destroy(&rpkt);
00871 return ret;
00872 }
00873 if (rt->state == STATE_STOPPED) {
00874 ff_rtmp_packet_destroy(&rpkt);
00875 return AVERROR_EOF;
00876 }
00877 if (for_header && (rt->state == STATE_PLAYING || rt->state == STATE_PUBLISHING)) {
00878 ff_rtmp_packet_destroy(&rpkt);
00879 return 0;
00880 }
00881 if (!rpkt.data_size || !rt->is_input) {
00882 ff_rtmp_packet_destroy(&rpkt);
00883 continue;
00884 }
00885 if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO ||
00886 (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) {
00887 ts = rpkt.timestamp;
00888
00889
00890 rt->flv_off = 0;
00891 rt->flv_size = rpkt.data_size + 15;
00892 rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size);
00893 bytestream_put_byte(&p, rpkt.type);
00894 bytestream_put_be24(&p, rpkt.data_size);
00895 bytestream_put_be24(&p, ts);
00896 bytestream_put_byte(&p, ts >> 24);
00897 bytestream_put_be24(&p, 0);
00898 bytestream_put_buffer(&p, rpkt.data, rpkt.data_size);
00899 bytestream_put_be32(&p, 0);
00900 ff_rtmp_packet_destroy(&rpkt);
00901 return 0;
00902 } else if (rpkt.type == RTMP_PT_METADATA) {
00903
00904 rt->flv_off = 0;
00905 rt->flv_size = rpkt.data_size;
00906 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
00907
00908 next = rpkt.data;
00909 ts = rpkt.timestamp;
00910 while (next - rpkt.data < rpkt.data_size - 11) {
00911 next++;
00912 data_size = bytestream_get_be24(&next);
00913 p=next;
00914 cts = bytestream_get_be24(&next);
00915 cts |= bytestream_get_byte(&next) << 24;
00916 if (pts==0)
00917 pts=cts;
00918 ts += cts - pts;
00919 pts = cts;
00920 bytestream_put_be24(&p, ts);
00921 bytestream_put_byte(&p, ts >> 24);
00922 next += data_size + 3 + 4;
00923 }
00924 memcpy(rt->flv_data, rpkt.data, rpkt.data_size);
00925 ff_rtmp_packet_destroy(&rpkt);
00926 return 0;
00927 }
00928 ff_rtmp_packet_destroy(&rpkt);
00929 }
00930 }
00931
00932 static int rtmp_close(URLContext *h)
00933 {
00934 RTMPContext *rt = h->priv_data;
00935 int ret = 0;
00936
00937 if (!rt->is_input) {
00938 rt->flv_data = NULL;
00939 if (rt->out_pkt.data_size)
00940 ff_rtmp_packet_destroy(&rt->out_pkt);
00941 if (rt->state > STATE_FCPUBLISH)
00942 ret = gen_fcunpublish_stream(h, rt);
00943 }
00944 if (rt->state > STATE_HANDSHAKED)
00945 ret = gen_delete_stream(h, rt);
00946
00947 av_freep(&rt->flv_data);
00948 ffurl_close(rt->stream);
00949 return ret;
00950 }
00951
00961 static int rtmp_open(URLContext *s, const char *uri, int flags)
00962 {
00963 RTMPContext *rt = s->priv_data;
00964 char proto[8], hostname[256], path[1024], *fname;
00965 char *old_app;
00966 uint8_t buf[2048];
00967 int port;
00968 int ret;
00969
00970 rt->is_input = !(flags & AVIO_FLAG_WRITE);
00971
00972 av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
00973 path, sizeof(path), s->filename);
00974
00975 if (port < 0)
00976 port = RTMP_DEFAULT_PORT;
00977 ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
00978
00979 if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
00980 &s->interrupt_callback, NULL)) < 0) {
00981 av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
00982 goto fail;
00983 }
00984
00985 rt->state = STATE_START;
00986 if ((ret = rtmp_handshake(s, rt)) < 0)
00987 goto fail;
00988
00989 rt->chunk_size = 128;
00990 rt->state = STATE_HANDSHAKED;
00991
00992
00993 old_app = rt->app;
00994
00995 rt->app = av_malloc(APP_MAX_LENGTH);
00996 if (!rt->app) {
00997 ret = AVERROR(ENOMEM);
00998 goto fail;
00999 }
01000
01001
01002 if (!strncmp(path, "/ondemand/", 10)) {
01003 fname = path + 10;
01004 memcpy(rt->app, "ondemand", 9);
01005 } else {
01006 char *next = *path ? path + 1 : path;
01007 char *p = strchr(next, '/');
01008 if (!p) {
01009 fname = next;
01010 rt->app[0] = '\0';
01011 } else {
01012 char *c = strchr(p + 1, ':');
01013 fname = strchr(p + 1, '/');
01014 if (!fname || c < fname) {
01015 fname = p + 1;
01016 av_strlcpy(rt->app, path + 1, p - path);
01017 } else {
01018 fname++;
01019 av_strlcpy(rt->app, path + 1, fname - path - 1);
01020 }
01021 }
01022 }
01023
01024 if (old_app) {
01025
01026 av_free(rt->app);
01027 rt->app = old_app;
01028 }
01029
01030 if (!rt->playpath) {
01031 rt->playpath = av_malloc(PLAYPATH_MAX_LENGTH);
01032 if (!rt->playpath) {
01033 ret = AVERROR(ENOMEM);
01034 goto fail;
01035 }
01036
01037 if (!strchr(fname, ':') &&
01038 (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
01039 !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
01040 memcpy(rt->playpath, "mp4:", 5);
01041 } else {
01042 rt->playpath[0] = 0;
01043 }
01044 strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
01045 }
01046
01047 if (!rt->tcurl) {
01048 rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
01049 if (!rt->tcurl) {
01050 ret = AVERROR(ENOMEM);
01051 goto fail;
01052 }
01053 ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
01054 port, "/%s", rt->app);
01055 }
01056
01057 if (!rt->flashver) {
01058 rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
01059 if (!rt->flashver) {
01060 ret = AVERROR(ENOMEM);
01061 goto fail;
01062 }
01063 if (rt->is_input) {
01064 snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
01065 RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
01066 RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
01067 } else {
01068 snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
01069 "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
01070 }
01071 }
01072
01073 rt->client_report_size = 1048576;
01074 rt->bytes_read = 0;
01075 rt->last_bytes_read = 0;
01076
01077 av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
01078 proto, path, rt->app, rt->playpath);
01079 if ((ret = gen_connect(s, rt)) < 0)
01080 goto fail;
01081
01082 do {
01083 ret = get_packet(s, 1);
01084 } while (ret == EAGAIN);
01085 if (ret < 0)
01086 goto fail;
01087
01088 if (rt->is_input) {
01089
01090 rt->flv_size = 13;
01091 rt->flv_data = av_realloc(rt->flv_data, rt->flv_size);
01092 rt->flv_off = 0;
01093 memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", rt->flv_size);
01094 } else {
01095 rt->flv_size = 0;
01096 rt->flv_data = NULL;
01097 rt->flv_off = 0;
01098 rt->skip_bytes = 13;
01099 }
01100
01101 s->max_packet_size = rt->stream->max_packet_size;
01102 s->is_streamed = 1;
01103 return 0;
01104
01105 fail:
01106 rtmp_close(s);
01107 return ret;
01108 }
01109
01110 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
01111 {
01112 RTMPContext *rt = s->priv_data;
01113 int orig_size = size;
01114 int ret;
01115
01116 while (size > 0) {
01117 int data_left = rt->flv_size - rt->flv_off;
01118
01119 if (data_left >= size) {
01120 memcpy(buf, rt->flv_data + rt->flv_off, size);
01121 rt->flv_off += size;
01122 return orig_size;
01123 }
01124 if (data_left > 0) {
01125 memcpy(buf, rt->flv_data + rt->flv_off, data_left);
01126 buf += data_left;
01127 size -= data_left;
01128 rt->flv_off = rt->flv_size;
01129 return data_left;
01130 }
01131 if ((ret = get_packet(s, 0)) < 0)
01132 return ret;
01133 }
01134 return orig_size;
01135 }
01136
01137 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
01138 {
01139 RTMPContext *rt = s->priv_data;
01140 int size_temp = size;
01141 int pktsize, pkttype;
01142 uint32_t ts;
01143 const uint8_t *buf_temp = buf;
01144 int ret;
01145
01146 do {
01147 if (rt->skip_bytes) {
01148 int skip = FFMIN(rt->skip_bytes, size_temp);
01149 buf_temp += skip;
01150 size_temp -= skip;
01151 rt->skip_bytes -= skip;
01152 continue;
01153 }
01154
01155 if (rt->flv_header_bytes < 11) {
01156 const uint8_t *header = rt->flv_header;
01157 int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
01158 bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
01159 rt->flv_header_bytes += copy;
01160 size_temp -= copy;
01161 if (rt->flv_header_bytes < 11)
01162 break;
01163
01164 pkttype = bytestream_get_byte(&header);
01165 pktsize = bytestream_get_be24(&header);
01166 ts = bytestream_get_be24(&header);
01167 ts |= bytestream_get_byte(&header) << 24;
01168 bytestream_get_be24(&header);
01169 rt->flv_size = pktsize;
01170
01171
01172 if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
01173 pkttype == RTMP_PT_NOTIFY) {
01174 if (pkttype == RTMP_PT_NOTIFY)
01175 pktsize += 16;
01176 rt->prev_pkt[1][RTMP_SOURCE_CHANNEL].channel_id = 0;
01177 }
01178
01179
01180 if ((ret = ff_rtmp_packet_create(&rt->out_pkt, RTMP_SOURCE_CHANNEL,
01181 pkttype, ts, pktsize)) < 0)
01182 return ret;
01183
01184 rt->out_pkt.extra = rt->main_channel_id;
01185 rt->flv_data = rt->out_pkt.data;
01186
01187 if (pkttype == RTMP_PT_NOTIFY)
01188 ff_amf_write_string(&rt->flv_data, "@setDataFrame");
01189 }
01190
01191 if (rt->flv_size - rt->flv_off > size_temp) {
01192 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
01193 rt->flv_off += size_temp;
01194 size_temp = 0;
01195 } else {
01196 bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
01197 size_temp -= rt->flv_size - rt->flv_off;
01198 rt->flv_off += rt->flv_size - rt->flv_off;
01199 }
01200
01201 if (rt->flv_off == rt->flv_size) {
01202 rt->skip_bytes = 4;
01203
01204 ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
01205 ff_rtmp_packet_destroy(&rt->out_pkt);
01206 rt->flv_size = 0;
01207 rt->flv_off = 0;
01208 rt->flv_header_bytes = 0;
01209 }
01210 } while (buf_temp - buf < size);
01211 return size;
01212 }
01213
01214 #define OFFSET(x) offsetof(RTMPContext, x)
01215 #define DEC AV_OPT_FLAG_DECODING_PARAM
01216 #define ENC AV_OPT_FLAG_ENCODING_PARAM
01217
01218 static const AVOption rtmp_options[] = {
01219 {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
01220 {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
01221 {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
01222 {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
01223 {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
01224 {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
01225 {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
01226 {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
01227 {"rtmp_tcurl", "URL of the target stream. Defaults to rtmp://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
01228 { NULL },
01229 };
01230
01231 static const AVClass rtmp_class = {
01232 .class_name = "rtmp",
01233 .item_name = av_default_item_name,
01234 .option = rtmp_options,
01235 .version = LIBAVUTIL_VERSION_INT,
01236 };
01237
01238 URLProtocol ff_rtmp_protocol = {
01239 .name = "rtmp",
01240 .url_open = rtmp_open,
01241 .url_read = rtmp_read,
01242 .url_write = rtmp_write,
01243 .url_close = rtmp_close,
01244 .priv_data_size = sizeof(RTMPContext),
01245 .flags = URL_PROTOCOL_FLAG_NETWORK,
01246 .priv_data_class= &rtmp_class,
01247 };