#include "flv.h" #include #include #include #include #include #include #include int MyRTMP_Write (RTMP* r, const char* buf, int size) { RTMPPacket* pkt = &r->m_write; char* enc; int s2 = size, ret, num; pkt->m_nChannel = 0x04; /* source channel */ pkt->m_nInfoField2 = r->m_stream_id; while (s2) { if (!pkt->m_nBytesRead) { if (size < 11) { /* FLV pkt too small */ return 0; } if (buf[0] == 'F' && buf[1] == 'L' && buf[2] == 'V') { buf += 13; s2 -= 13; } pkt->m_packetType = *buf++; pkt->m_nBodySize = AMF_DecodeInt24 (buf); buf += 3; pkt->m_nTimeStamp = AMF_DecodeInt24 (buf); buf += 3; pkt->m_nTimeStamp |= *buf++ << 24; buf += 3; s2 -= 11; if ( ( (pkt->m_packetType == RTMP_PACKET_TYPE_AUDIO || pkt->m_packetType == RTMP_PACKET_TYPE_VIDEO) && !pkt->m_nTimeStamp) || pkt->m_packetType == RTMP_PACKET_TYPE_INFO) { pkt->m_headerType = RTMP_PACKET_SIZE_LARGE; } else { pkt->m_headerType = RTMP_PACKET_SIZE_MEDIUM; } if (!RTMPPacket_Alloc (pkt, pkt->m_nBodySize)) { RTMP_Log (RTMP_LOGDEBUG, "%s, failed to allocate packet", __FUNCTION__); return FALSE; } enc = pkt->m_body; } else { enc = pkt->m_body + pkt->m_nBytesRead; } num = pkt->m_nBodySize - pkt->m_nBytesRead; if (num > s2) { num = s2; } memcpy (enc, buf, num); pkt->m_nBytesRead += num; s2 -= num; buf += num; if (pkt->m_nBytesRead == pkt->m_nBodySize) { ret = RTMP_SendPacket (r, pkt, FALSE); RTMPPacket_Free (pkt); pkt->m_nBytesRead = 0; if (!ret) { return -1; } buf += 4; s2 -= 4; if (s2 < 0) { break; } } } return size+s2; } int main (int argc, const char** argv) { FILE* flv; RTMP* rtmp; RTMPPacket rtmpPacket; flvtag_t tag; int32_t timestamp = 0; int has_audio, has_video; char* url = 0; if (2 >= argc) { fprintf (stderr,"Usage %s [input] [url]\n",argv[0]); } url = (char*) argv[2]; flv = flv_open_read (argv[1]); if (! flv) { fprintf (stderr,"Could not open %s\n",argv[1]); return EXIT_FAILURE; } if (! flv_read_header (flv, &has_audio, &has_video)) { fprintf (stderr,"Not an flv file %s\n",argv[1]); return EXIT_FAILURE; } flvtag_init (&tag); rtmp = RTMP_Alloc(); RTMP_Init (rtmp); fprintf (stderr,"Connecting to %s\n", url); RTMP_SetupURL (rtmp, url); RTMP_EnableWrite (rtmp); RTMP_Connect (rtmp, NULL); RTMP_ConnectStream (rtmp, 0); memset (&rtmpPacket, 0, sizeof (RTMPPacket)); if (! RTMP_IsConnected (rtmp)) { fprintf (stderr,"RTMP_IsConnected() Error\n"); return EXIT_FAILURE; } while (flv_read_tag (flv,&tag)) { if (! RTMP_IsConnected (rtmp) || RTMP_IsTimedout (rtmp)) { fprintf (stderr,"RTMP_IsConnected() Error\n"); return EXIT_FAILURE; } if (flvtag_timestamp (&tag) > timestamp) { usleep (1000 * (flvtag_timestamp (&tag) - timestamp)); timestamp = flvtag_timestamp (&tag); } MyRTMP_Write (rtmp, (const char*) flvtag_raw_data (&tag),flvtag_raw_size (&tag)); // Handle RTMP ping and such fd_set sockset; struct timeval timeout = {0,0}; FD_ZERO (&sockset); FD_SET (RTMP_Socket (rtmp), &sockset); register int result = select (RTMP_Socket (rtmp) + 1, &sockset, NULL, NULL, &timeout); if (result == 1 && FD_ISSET (RTMP_Socket (rtmp), &sockset)) { RTMP_ReadPacket (rtmp, &rtmpPacket); if (! RTMPPacket_IsReady (&rtmpPacket)) { fprintf (stderr,"Received RTMP packet\n"); RTMP_ClientPacket (rtmp,&rtmpPacket); RTMPPacket_Free (&rtmpPacket); } } } return EXIT_SUCCESS; }