int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, uint8_t *buf, int buf_size) { RTSPState *rt = s->priv_data; int id, len, i, ret; RTSPStream *rtsp_st; #ifdef DEBUG_RTP_TCP av_dlog(s, "tcp_read_packet:\n"); #endif redo: for (;;) { RTSPMessageHeader reply; ret = ff_rtsp_read_reply(s, &reply, NULL, 1, NULL); if (ret < 0) return ret; if (ret == 1) /* received '$' */ break; /* XXX: parse message */ if (rt->state != RTSP_STATE_STREAMING) return 0; } ret = url_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) return -1; id = buf[0]; len = AV_RB16(buf + 1); #ifdef DEBUG_RTP_TCP av_dlog(s, "id=%d len=%d\n", id, len); #endif if (len > buf_size || len < 12) goto redo; /* get the data */ ret = url_read_complete(rt->rtsp_hd, buf, len); if (ret != len) return -1; if (rt->transport == RTSP_TRANSPORT_RDT && ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0) return -1; /* find the matching stream */ for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (id >= rtsp_st->interleaved_min && id <= rtsp_st->interleaved_max) goto found; } goto redo; found: *prtsp_st = rtsp_st; return len; }
static int read_data_packet(MMSHContext *mmsh, const int len) { MMSContext *mms = &mmsh->mms; int res; if (len > sizeof(mms->in_buffer)) { av_log(NULL, AV_LOG_ERROR, "Data packet length %d exceeds the in_buffer size %zu\n", len, sizeof(mms->in_buffer)); return AVERROR(EIO); } res = url_read_complete(mms->mms_hd, mms->in_buffer, len); av_dlog(NULL, "Data packet len = %d\n", len); if (res != len) { av_log(NULL, AV_LOG_ERROR, "Read data packet failed!\n"); return AVERROR(EIO); } if (len > mms->asf_packet_len) { av_log(NULL, AV_LOG_ERROR, "Chunk length %d exceed packet length %d\n",len, mms->asf_packet_len); return AVERROR_INVALIDDATA; } else { memset(mms->in_buffer + len, 0, mms->asf_packet_len - len); // padding } mms->read_in_ptr = mms->in_buffer; mms->remaining_in_len = mms->asf_packet_len; return 0; }
static ChunkType get_chunk_header(MMSHContext *mmsh, int *len) { MMSContext *mms = &mmsh->mms; uint8_t chunk_header[CHUNK_HEADER_LENGTH]; uint8_t ext_header[EXT_HEADER_LENGTH]; ChunkType chunk_type; int chunk_len, res, ext_header_len; res = url_read_complete(mms->mms_hd, chunk_header, CHUNK_HEADER_LENGTH); if (res != CHUNK_HEADER_LENGTH) { av_log(NULL, AV_LOG_ERROR, "Read data packet header failed!\n"); return AVERROR(EIO); } chunk_type = AV_RL16(chunk_header); chunk_len = AV_RL16(chunk_header + 2); switch (chunk_type) { case CHUNK_TYPE_END: case CHUNK_TYPE_STREAM_CHANGE: ext_header_len = 4; break; case CHUNK_TYPE_ASF_HEADER: case CHUNK_TYPE_DATA: ext_header_len = 8; break; default: av_log(NULL, AV_LOG_ERROR, "Strange chunk type %d\n", chunk_type); return AVERROR_INVALIDDATA; } res = url_read_complete(mms->mms_hd, ext_header, ext_header_len); if (res != ext_header_len) { av_log(NULL, AV_LOG_ERROR, "Read ext header failed!\n"); return AVERROR(EIO); } *len = chunk_len - ext_header_len; if (chunk_type == CHUNK_TYPE_END || chunk_type == CHUNK_TYPE_DATA) mmsh->chunk_seq = AV_RL32(ext_header); return chunk_type; }
static int get_http_header_data(MMSHContext *mmsh) { MMSContext *mms = &mmsh->mms; int res, len; ChunkType chunk_type; for (;;) { len = 0; res = chunk_type = get_chunk_header(mmsh, &len); if (res < 0) { return res; } else if (chunk_type == CHUNK_TYPE_ASF_HEADER){ // get asf header and stored it if (!mms->header_parsed) { if (mms->asf_header) { if (len != mms->asf_header_size) { mms->asf_header_size = len; av_dlog(NULL, "Header len changed from %d to %d\n", mms->asf_header_size, len); av_freep(&mms->asf_header); } } mms->asf_header = av_mallocz(len); if (!mms->asf_header) { return AVERROR(ENOMEM); } mms->asf_header_size = len; } if (len > mms->asf_header_size) { av_log(NULL, AV_LOG_ERROR, "Asf header packet len = %d exceed the asf header buf size %d\n", len, mms->asf_header_size); return AVERROR(EIO); } res = url_read_complete(mms->mms_hd, mms->asf_header, len); if (res != len) { av_log(NULL, AV_LOG_ERROR, "Recv asf header data len %d != expected len %d\n", res, len); return AVERROR(EIO); } mms->asf_header_size = len; if (!mms->header_parsed) { res = ff_mms_asf_header_parser(mms); mms->header_parsed = 1; return res; } } else if (chunk_type == CHUNK_TYPE_DATA) { // read data packet and do padding return read_data_packet(mmsh, len); } else { if (len) { if (len > sizeof(mms->in_buffer)) { av_log(NULL, AV_LOG_ERROR, "Other packet len = %d exceed the in_buffer size %zu\n", len, sizeof(mms->in_buffer)); return AVERROR(EIO); } res = url_read_complete(mms->mms_hd, mms->in_buffer, len); if (res != len) { av_log(NULL, AV_LOG_ERROR, "Read other chunk type data failed!\n"); return AVERROR(EIO); } else { av_dlog(NULL, "Skip chunk type %d \n", chunk_type); continue; } } } } return 0; }
int StreamingRingBuffer::safe_read(void *data, uint sz) { if (m_context) return url_read_complete(m_context, (unsigned char*)data, sz); return 0; }
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt) { uint8_t hdr, t, buf[16]; int channel_id, timestamp, data_size, offset = 0; uint32_t extra = 0; enum RTMPPacketType type; int size = 0; if (url_read(h, &hdr, 1) != 1) return AVERROR(EIO); size++; channel_id = hdr & 0x3F; if (channel_id < 2) { //special case for channel number >= 64 buf[1] = 0; if (url_read_complete(h, buf, channel_id + 1) != channel_id + 1) return AVERROR(EIO); size += channel_id + 1; channel_id = AV_RL16(buf) + 64; } data_size = prev_pkt[channel_id].data_size; type = prev_pkt[channel_id].type; extra = prev_pkt[channel_id].extra; hdr >>= 6; if (hdr == RTMP_PS_ONEBYTE) { timestamp = prev_pkt[channel_id].ts_delta; } else { if (url_read_complete(h, buf, 3) != 3) return AVERROR(EIO); size += 3; timestamp = AV_RB24(buf); if (hdr != RTMP_PS_FOURBYTES) { if (url_read_complete(h, buf, 3) != 3) return AVERROR(EIO); size += 3; data_size = AV_RB24(buf); if (url_read_complete(h, buf, 1) != 1) return AVERROR(EIO); size++; type = buf[0]; if (hdr == RTMP_PS_TWELVEBYTES) { if (url_read_complete(h, buf, 4) != 4) return AVERROR(EIO); size += 4; extra = AV_RL32(buf); } } if (timestamp == 0xFFFFFF) { if (url_read_complete(h, buf, 4) != 4) return AVERROR(EIO); timestamp = AV_RB32(buf); } } if (hdr != RTMP_PS_TWELVEBYTES) timestamp += prev_pkt[channel_id].timestamp; if (ff_rtmp_packet_create(p, channel_id, type, timestamp, data_size)) return -1; p->extra = extra; // save history prev_pkt[channel_id].channel_id = channel_id; prev_pkt[channel_id].type = type; prev_pkt[channel_id].data_size = data_size; prev_pkt[channel_id].ts_delta = timestamp - prev_pkt[channel_id].timestamp; prev_pkt[channel_id].timestamp = timestamp; prev_pkt[channel_id].extra = extra; while (data_size > 0) { int toread = FFMIN(data_size, chunk_size); if (url_read_complete(h, p->data + offset, toread) != toread) { ff_rtmp_packet_destroy(p); return AVERROR(EIO); } data_size -= chunk_size; offset += chunk_size; size += chunk_size; if (data_size > 0) { url_read_complete(h, &t, 1); //marker size++; if (t != (0xC0 + channel_id)) return -1; } } return size; }
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int chunk_size, RTMPPacket *prev_pkt) { uint8_t hdr, t, buf[16]; int channel_id, timestamp, data_size, offset = 0; uint32_t extra = 0; uint8_t type; if (url_read(h, &hdr, 1) != 1) return AVERROR(EIO); channel_id = hdr & 0x3F; data_size = prev_pkt[channel_id].data_size; type = prev_pkt[channel_id].type; extra = prev_pkt[channel_id].extra; hdr >>= 6; if (hdr == RTMP_PS_ONEBYTE) { //todo return -1; } else { if (url_read_complete(h, buf, 3) != 3) return AVERROR(EIO); timestamp = AV_RB24(buf); if (hdr != RTMP_PS_FOURBYTES) { if (url_read_complete(h, buf, 3) != 3) return AVERROR(EIO); data_size = AV_RB24(buf); if (url_read_complete(h, &type, 1) != 1) return AVERROR(EIO); if (hdr == RTMP_PS_TWELVEBYTES) { if (url_read_complete(h, buf, 4) != 4) return AVERROR(EIO); extra = AV_RL32(buf); } } } if (ff_rtmp_packet_create(p, channel_id, type, timestamp, data_size)) return -1; p->extra = extra; // save history prev_pkt[channel_id].channel_id = channel_id; prev_pkt[channel_id].type = type; prev_pkt[channel_id].data_size = data_size; prev_pkt[channel_id].timestamp = timestamp; prev_pkt[channel_id].extra = extra; while (data_size > 0) { int toread = FFMIN(data_size, chunk_size); if (url_read_complete(h, p->data + offset, toread) != toread) { ff_rtmp_packet_destroy(p); return AVERROR(EIO); } data_size -= chunk_size; offset += chunk_size; if (data_size > 0) { url_read_complete(h, &t, 1); //marker if (t != (0xC0 + channel_id)) return -1; } } return 0; }
static int fill_buffer(stream_t *s, char *buffer, int max_len) { int r = url_read_complete(s->priv, buffer, max_len); return (r <= 0) ? -1 : r; }
/** Read incoming MMST media, header or command packet. */ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) { int read_result; MMSSCPacketType packet_type= -1; MMSContext *mms = &mmst->mms; for(;;) { read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8); if (read_result != 8) { if(read_result < 0) { av_log(NULL, AV_LOG_ERROR, "Error reading packet header: %d (%s)\n", read_result, strerror(read_result)); packet_type = SC_PKT_CANCEL; } else { av_log(NULL, AV_LOG_ERROR, "The server closed the connection\n"); packet_type = SC_PKT_NO_DATA; } return packet_type; } // handle command packet. if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { int length_remaining, hr; mmst->incoming_flags= mms->in_buffer[3]; read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); if(read_result != 4) { av_log(NULL, AV_LOG_ERROR, "Reading command packet length failed: %d (%s)\n", read_result, read_result < 0 ? strerror(read_result) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR_IO; } length_remaining= AV_RL32(mms->in_buffer+8) + 4; dprintf(NULL, "Length remaining is %d\n", length_remaining); // read the rest of the packet. if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 12) { av_log(NULL, AV_LOG_ERROR, "Incoming packet length %d exceeds bufsize %zu\n", length_remaining, sizeof(mms->in_buffer) - 12); return AVERROR_INVALIDDATA; } read_result = url_read_complete(mms->mms_hd, mms->in_buffer + 12, length_remaining) ; if (read_result != length_remaining) { av_log(NULL, AV_LOG_ERROR, "Reading pkt data (length=%d) failed: %d (%s)\n", length_remaining, read_result, read_result < 0 ? strerror(read_result) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR_IO; } packet_type= AV_RL16(mms->in_buffer+36); hr = AV_RL32(mms->in_buffer + 40); if (hr) { av_log(NULL, AV_LOG_ERROR, "Server sent an error status code: 0x%08x\n", hr); return AVERROR_UNKNOWN; } } else { int length_remaining; int packet_id_type; int tmp; // note we cache the first 8 bytes, // then fill up the buffer with the others tmp = AV_RL16(mms->in_buffer + 6); length_remaining = (tmp - 8) & 0xffff; mmst->incoming_packet_seq = AV_RL32(mms->in_buffer); packet_id_type = mms->in_buffer[4]; mmst->incoming_flags = mms->in_buffer[5]; if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 8) { av_log(NULL, AV_LOG_ERROR, "Data length %d is invalid or too large (max=%zu)\n", length_remaining, sizeof(mms->in_buffer)); return AVERROR_INVALIDDATA; } mms->remaining_in_len = length_remaining; mms->read_in_ptr = mms->in_buffer; read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_remaining); if(read_result != length_remaining) { av_log(NULL, AV_LOG_ERROR, "Failed to read packet data of size %d: %d (%s)\n", length_remaining, read_result, read_result < 0 ? strerror(read_result) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR_IO; } // if we successfully read everything. if(packet_id_type == mmst->header_packet_id) { packet_type = SC_PKT_ASF_HEADER; // Store the asf header if(!mms->header_parsed) { void *p = av_realloc(mms->asf_header, mms->asf_header_size + mms->remaining_in_len); if (!p) { av_freep(&mms->asf_header); return AVERROR(ENOMEM); } mms->asf_header = p; memcpy(mms->asf_header + mms->asf_header_size, mms->read_in_ptr, mms->remaining_in_len); mms->asf_header_size += mms->remaining_in_len; } // 0x04 means asf header is sent in multiple packets. if (mmst->incoming_flags == 0x04) continue; } else if(packet_id_type == mmst->packet_id) { packet_type = SC_PKT_ASF_MEDIA; } else { dprintf(NULL, "packet id type %d is old.", packet_id_type); continue; } } // preprocess some packet type if(packet_type == SC_PKT_KEEPALIVE) { send_keepalive_packet(mmst); continue; } else if(packet_type == SC_PKT_STREAM_CHANGING) { handle_packet_stream_changing_type(mmst); } else if(packet_type == SC_PKT_ASF_MEDIA) { pad_media_packet(mms); } return packet_type; } }
/** Read incoming MMST media, header or command packet. */ static MMSSCPacketType get_tcp_server_response(MMSContext *mms) { int read_result; MMSSCPacketType packet_type= -1; for(;;) { if((read_result= url_read_complete(mms->mms_hd, mms->in_buffer, 8))==8) { // handle command packet. if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { mms->incoming_flags= mms->in_buffer[3]; read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); if(read_result == 4) { int length_remaining= AV_RL32(mms->in_buffer+8) + 4; int hr; dprintf(NULL, "Length remaining is %d\n", length_remaining); // read the rest of the packet. if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 12) { dprintf(NULL, "Incoming message len %d exceeds buffer len %d\n", length_remaining, sizeof(mms->in_buffer) - 12); return -1; } read_result = url_read_complete(mms->mms_hd, mms->in_buffer + 12, length_remaining) ; if (read_result == length_remaining) { packet_type= AV_RL16(mms->in_buffer+36); } else { dprintf(NULL, "read for packet type failed%d!\n", read_result); return -1; } hr = AV_RL32(mms->in_buffer + 40); if (hr) { dprintf(NULL, "The server side send back error code:0x%x\n", hr); return -1; } } else { dprintf(NULL, "read for length remaining failed%d!\n", read_result); return -1; } } else { int length_remaining; int packet_id_type; int tmp; // note we cache the first 8 bytes, // then fill up the buffer with the others tmp = AV_RL16(mms->in_buffer + 6); length_remaining = (tmp - 8) & 0xffff; mms->incoming_packet_seq = AV_RL32(mms->in_buffer); packet_id_type = mms->in_buffer[4]; mms->incoming_flags = mms->in_buffer[5]; if (length_remaining < 0 || length_remaining > sizeof(mms->in_buffer) - 8) { dprintf(NULL, "Incoming data len %d exceeds buffer len %d\n", length_remaining, sizeof(mms->in_buffer)); return -1; } mms->remaining_in_len = length_remaining; mms->read_in_ptr = mms->in_buffer; read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_remaining); if(read_result != length_remaining) { dprintf(NULL, "read_bytes result: %d asking for %d\n", read_result, length_remaining); return -1; } else { // if we successfully read everything. if(packet_id_type == mms->header_packet_id) { packet_type = SC_PKT_ASF_HEADER; // Store the asf header if(!mms->header_parsed) { void *p = av_realloc(mms->asf_header, mms->asf_header_size + mms->remaining_in_len); if (!p) { av_freep(&mms->asf_header); return AVERROR(ENOMEM); } mms->asf_header = p; memcpy(mms->asf_header + mms->asf_header_size, mms->read_in_ptr, mms->remaining_in_len); mms->asf_header_size += mms->remaining_in_len; } // 0x04 means asf header is sent in multiple packets. if (mms->incoming_flags == 0x04) continue; } else if(packet_id_type == mms->packet_id) { packet_type = SC_PKT_ASF_MEDIA; } else { dprintf(NULL, "packet id type %d is old.", packet_id_type); continue; } } } // preprocess some packet type if(packet_type == SC_PKT_KEEPALIVE) { send_keepalive_packet(mms); continue; } else if(packet_type == SC_PKT_STREAM_CHANGING) { handle_packet_stream_changing_type(mms); } else if(packet_type == SC_PKT_ASF_MEDIA) { pad_media_packet(mms); } return packet_type; } else { if(read_result<0) { dprintf(NULL, "Read error (or cancelled) returned %d!\n", read_result); packet_type = SC_PKT_CANCEL; } else { dprintf(NULL, "Read result of zero?!\n"); packet_type = SC_PKT_NO_DATA; } return packet_type; } } }
int ReadFunc2(void *opaque, uint8_t *buf, int size) { DPRINTF(E_DBG, L_XCODE, "requested a read of %d bytes\n", size); struct icy_ctx *s = (struct icy_ctx *) opaque; URLContext *context = s->context; if ( !s->icy_metaint) return url_read_complete( context, buf, size ); int len = url_read_complete( context, buf, size ); int ldata = s->icy_metaint - s->data_pos; DPRINTF(E_DBG, L_XCODE, "current data pos %d\n", s->data_pos); /* pull out the Icy Metadata */ if ( s->data_pos + len > s->icy_metaint ) { DPRINTF(E_DBG, L_XCODE, "current packet has metadata. ldata %d len %d data_pos %d\n", ldata, len, s->data_pos); while ( ldata < len ) { int md_size = *(buf + ldata) * 16; /* determine how much data to copy initially */ DPRINTF(E_DBG, L_XCODE, "found a metatag of %d bytes\n", md_size); int md_len = (ldata + md_size + 1 > len) ? len - ldata - 1: md_size; if (md_size > 0) { /* parse out the metadata */ uint8_t *md = (uint8_t*)av_malloc(sizeof(uint8_t) * (md_size + 1)); if (md != NULL) { int md_total = md_len; /* copy in whatever metadata we already have */ memcpy(md, buf + ldata + 1, md_len); /* get the rest of the metadata */ if (md_total < md_size) { do { md_total += url_read(context, md + md_total, md_size - md_total); } while (md_total < md_size); } } md[md_size] = 0; http_parse_metadata(s, md, md_size); av_free(md); } s->data_pos = 0; if (ldata + md_len + 1 < len) { /* copy any leftover data */ int ridx = ldata + md_len + 1; int rlen = len - ridx; memcpy(buf + ldata, buf + ridx, rlen); s->data_pos = rlen; } ldata+= s->icy_metaint; /* zero length returns cause problems (metadata only bufs) */ if ((len -= (md_len + 1)) == 0) { len = url_read(context, buf, size); } } } else if (s->icy_metaint) { s->data_pos += len; } DPRINTF(E_DBG, L_XCODE, "returning %d\n",len); return len; }