/*---------------------------------------------------------------------------*/ static PT_THREAD(pingreq_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending PINGREQ\n"); /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_PINGREQ); PT_MQTT_WRITE_BYTE(conn, 0); send_out_buffer(conn); /* Start timeout for reply. */ conn->waiting_for_pingresp = 1; /* Wait for PINGRESP or timeout */ reset_packet(&conn->in_packet); timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); PT_WAIT_UNTIL(pt, conn->in_packet.packet_received || timer_expired(&conn->t)); reset_packet(&conn->in_packet); conn->waiting_for_pingresp = 0; PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(pingreq_pt(struct pt* pt, struct mqtt_connection* conn)) { PT_BEGIN(pt); DBG("MQTT - Sending PINGREQ\r\n"); /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_PINGREQ); PT_MQTT_WRITE_BYTE(conn, 0); send_out_buffer(conn); PT_WAIT_UNTIL(pt, conn->out_buffer_sent); /* Start timeout for reply. */ conn->waiting_for_pingresp = 1; /* Wait for PINGRESP * * Note that the timeout disconnect is handle in the timer callback. */ reset_packet(&conn->in_packet); do { PT_WAIT_UNTIL(pt, conn->in_packet.packet_received); } while((conn->in_packet.fhdr & 0xF0) != MQTT_FHDR_MSG_TYPE_PINGRESP); reset_packet(&conn->in_packet); conn->waiting_for_pingresp = 0; PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(subscribe_pt(struct pt* pt, struct mqtt_connection* conn)) { PT_BEGIN(pt); DBG("MQTT - Sending subscribe message! topic %s topic_length %i\r\n", conn->out_packet.topic, conn->out_packet.topic_length); DBG("MQTT - Buffer space is %i \r\n", &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_SUBSCRIBE | MQTT_FHDR_QOS_LEVEL_1; conn->out_packet.remaining_length = MQTT_MID_SIZE + MQTT_STRING_LEN_SIZE + conn->out_packet.topic_length + MQTT_QOS_SIZE; encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); printf("MQTT - Error, remaining length > 4 bytes\r\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); /* Write Variable Header */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); /* Write Payload */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.topic, conn->out_packet.topic_length); PT_MQTT_WRITE_BYTE(conn, conn->out_packet.qos); /* Send out buffer */ send_out_buffer(conn); /* Wait for SUBACK. */ reset_packet(&conn->in_packet); do { PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK); } while(conn->out_packet.qos_state != MQTT_QOS_STATE_GOT_ACK); reset_packet(&conn->in_packet); /* This is clear after the entire transaction is complete */ conn->out_queue_full = 0; DBG("MQTT - Done in send_subscribe!\r\n"); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static void handle_publish(struct mqtt_connection *conn) { DBG("MQTT - Got PUBLISH, called once per manageable chunk of message.\n"); DBG("MQTT - Handling publish on topic '%s'\n", conn->in_publish_msg.topic); DBG("MQTT - This chunk is %i bytes\n", conn->in_packet.payload_pos); if(((conn->in_packet.fhdr & 0x09) >> 1) > 0) { PRINTF("MQTT - Error, got incoming PUBLISH with QoS > 0, not supported atm!\n"); } call_event(conn, MQTT_EVENT_PUBLISH, &conn->in_publish_msg); if(conn->in_publish_msg.first_chunk == 1) { conn->in_publish_msg.first_chunk = 0; } /* If this is the last time handle_publish will be called, reset packet. */ if(conn->in_publish_msg.payload_left == 0) { /* Check for QoS and initiate the reply, do not rely on the data in the * in_packet being untouched. */ DBG("MQTT - (handle_publish) resetting packet.\n"); reset_packet(&conn->in_packet); } }
static int hls_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { HLSContext *c = s->priv_data; int i, j, ret; if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished) return AVERROR(ENOSYS); c->seek_flags = flags; c->seek_timestamp = stream_index < 0 ? timestamp : av_rescale_rnd(timestamp, AV_TIME_BASE, s->streams[stream_index]->time_base.den, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); if (s->duration < c->seek_timestamp) { c->seek_timestamp = AV_NOPTS_VALUE; return AVERROR(EIO); } ret = AVERROR(EIO); for (i = 0; i < c->n_variants; i++) { /* Reset reading */ struct variant *var = c->variants[i]; int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 : av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); if (var->input) { ffurl_close(var->input); var->input = NULL; } av_free_packet(&var->pkt); reset_packet(&var->pkt); var->pb.eof_reached = 0; /* Clear any buffered data */ var->pb.buf_end = var->pb.buf_ptr = var->pb.buffer; /* Reset the pos, to let the mpegts demuxer know we've seeked. */ var->pb.pos = 0; /* Locate the segment that contains the target timestamp */ for (j = 0; j < var->n_segments; j++) { if (timestamp >= pos && timestamp < pos + var->segments[j]->duration) { var->cur_seq_no = var->start_seq_no + j; ret = 0; break; } pos += var->segments[j]->duration; } if (ret) c->seek_timestamp = AV_NOPTS_VALUE; } return ret; }
static int applehttp_read_packet(AVFormatContext *s, AVPacket *pkt) { AppleHTTPContext *c = s->priv_data; int ret, i, minvariant = -1; if (c->first_packet) { recheck_discard_flags(s, 1); c->first_packet = 0; } start: c->end_of_segment = 0; for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; /* Make sure we've got one buffered packet from each open variant * stream */ if (var->needed && !var->pkt.data) { ret = av_read_frame(var->ctx, &var->pkt); if (ret < 0) { if (!var->pb.eof_reached) return ret; reset_packet(&var->pkt); } else { if (c->first_timestamp == AV_NOPTS_VALUE) c->first_timestamp = var->pkt.dts; } } /* Check if this stream has the packet with the lowest dts */ if (var->pkt.data) { if (minvariant < 0 || var->pkt.dts < c->variants[minvariant]->pkt.dts) minvariant = i; } } if (c->end_of_segment) { if (recheck_discard_flags(s, 0)) goto start; } /* If we got a packet, return it */ if (minvariant >= 0) { *pkt = c->variants[minvariant]->pkt; pkt->stream_index += c->variants[minvariant]->stream_offset; reset_packet(&c->variants[minvariant]->pkt); return 0; } return AVERROR_EOF; }
/*---------------------------------------------------------------------------*/ static void reset_defaults(struct mqtt_connection *conn) { conn->mid_counter = 1; PT_INIT(&conn->out_proto_thread); conn->waiting_for_pingresp = 0; reset_packet(&conn->in_packet); conn->out_buffer_sent = 0; }
static struct playlist *new_playlist(HLSContext *c, const char *url, const char *base) { struct playlist *pls = av_mallocz(sizeof(struct playlist)); if (!pls) return NULL; reset_packet(&pls->pkt); ff_make_absolute_url(pls->url, sizeof(pls->url), base, url); dynarray_add(&c->playlists, &c->n_playlists, pls); return pls; }
static struct variant *new_variant(HLSContext *c, int bandwidth, const char *url, const char *base) { struct variant *var = av_mallocz(sizeof(struct variant)); if (!var) return NULL; reset_packet(&var->pkt); var->bandwidth = bandwidth; ff_make_absolute_url(var->url, sizeof(var->url), base, url); dynarray_add(&c->variants, &c->n_variants, var); return var; }
static int applehttp_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { AppleHTTPContext *c = s->priv_data; int i, j, ret; if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished) return AVERROR(ENOSYS); timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); ret = AVERROR(EIO); for (i = 0; i < c->n_variants; i++) { /* Reset reading */ struct variant *var = c->variants[i]; int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 : av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); if (var->input) { ffurl_close(var->input); var->input = NULL; } av_free_packet(&var->pkt); reset_packet(&var->pkt); var->pb.eof_reached = 0; /* Locate the segment that contains the target timestamp */ for (j = 0; j < var->n_segments; j++) { if (timestamp >= pos && timestamp < pos + var->segments[j]->duration) { var->cur_seq_no = var->start_seq_no + j; ret = 0; break; } pos += var->segments[j]->duration; } } return ret; }
static int open_variant(AppleHTTPContext *c, struct variant *var, int skip) { int ret; if (c->cur_seq_no < var->start_seq_no) { av_log(NULL, AV_LOG_WARNING, "seq %d not available in variant %s, skipping\n", var->start_seq_no, var->url); return 0; } if (c->cur_seq_no - var->start_seq_no >= var->n_segments) return c->finished ? AVERROR_EOF : 0; ret = url_fopen(&var->pb, var->segments[c->cur_seq_no - var->start_seq_no]->url, URL_RDONLY); if (ret < 0) return ret; var->ctx->pb = var->pb; /* If this is a new segment in parallel with another one already opened, * skip ahead so they're all at the same dts. */ if (skip && c->last_packet_dts != AV_NOPTS_VALUE) { while (1) { ret = av_read_frame(var->ctx, &var->pkt); if (ret < 0) { if (ret == AVERROR_EOF) { reset_packet(&var->pkt); return 0; } return ret; } if (var->pkt.dts >= c->last_packet_dts) break; av_free_packet(&var->pkt); } } return 0; }
int alloc_free_queue(nic_t *nic, size_t num_of_packets) { int i; pthread_mutex_lock(&nic->free_packet_queue_mutex); for (i = 0; i < num_of_packets; i++) { packet_t *pkt; pkt = alloc_packet(STD_MTU_SIZE, STD_MTU_SIZE); if (pkt == NULL) { goto done; } reset_packet(pkt); pkt->next = nic->free_packet_queue; nic->free_packet_queue = pkt; } done: pthread_mutex_unlock(&nic->free_packet_queue_mutex); return i; }
static int applehttp_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { AppleHTTPContext *c = s->priv_data; int pos = 0, i; struct variant *var = c->variants[0]; if ((flags & AVSEEK_FLAG_BYTE) || !c->finished) return AVERROR(ENOSYS); /* Reset the variants */ c->last_packet_dts = AV_NOPTS_VALUE; for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; if (var->pb) { url_fclose(var->pb); var->pb = NULL; } av_free_packet(&var->pkt); reset_packet(&var->pkt); } timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); /* Locate the segment that contains the target timestamp */ for (i = 0; i < var->n_segments; i++) { if (timestamp >= pos && timestamp < pos + var->segments[i]->duration) { c->cur_seq_no = var->start_seq_no + i; return 0; } pos += var->segments[i]->duration; } return AVERROR(EIO); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(connect_pt(struct pt* pt, struct mqtt_connection* conn)) { PT_BEGIN(pt); DBG("MQTT - Sending CONNECT message...\r\n"); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT; conn->out_packet.remaining_length = 0; conn->out_packet.remaining_length += MQTT_connect_vhdr_flags_SIZE; conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message); encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); printf("MQTT - Error, remaining length > 4 bytes\r\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); PT_MQTT_WRITE_BYTE(conn, 0); PT_MQTT_WRITE_BYTE(conn, 6); PT_MQTT_WRITE_BYTES(conn, (uint8_t*)MQTT_PROTOCOL_NAME, 6); PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION); PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF)); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->client_id.string, conn->client_id.length); if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->will.topic.string, conn->will.topic.length); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->will.message.string, conn->will.message.length); DBG("MQTT - Setting will topic to '%s' %i bytes and message to '%s' %i bytes\r\n", conn->will.topic.string, conn->will.topic.length, conn->will.message.string, conn->will.message.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) { DBG("MQTT - Setting username\r\n"); PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->credentials.username.string, conn->credentials.username.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) { DBG("MQTT - Setting password\r\n"); PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->credentials.password.string, conn->credentials.password.length); } /* Send out buffer */ send_out_buffer(conn); conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER; /* Wait for CONNACK */ reset_packet(&conn->in_packet); do { PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK); } while(conn->out_packet.qos_state != MQTT_QOS_STATE_GOT_ACK); reset_packet(&conn->in_packet); DBG("MQTT - Done sending CONNECT since we got CONNACK!\r\n"); #if DEBUG_MQTT == 1 DBG("MQTT - Sending CONNECT message: \r\n"); uint16_t i; for( i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++ ) { DBG( "%02X ", conn->out_buffer[i] ); } DBG("\r\n"); #endif PT_END(pt); }
static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) { HLSContext *c = s->priv_data; int ret, i, minvariant = -1; if (c->first_packet) { recheck_discard_flags(s, 1); c->first_packet = 0; } start: c->end_of_segment = 0; for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; /* Make sure we've got one buffered packet from each open variant * stream */ if (var->needed && !var->pkt.data) { while (1) { int64_t ts_diff; AVStream *st; ret = av_read_frame(var->ctx, &var->pkt); if (ret < 0) { if (!url_feof(&var->pb) && ret != AVERROR_EOF) return ret; reset_packet(&var->pkt); break; } else { if (c->first_timestamp == AV_NOPTS_VALUE) c->first_timestamp = var->pkt.dts; } if (c->seek_timestamp == AV_NOPTS_VALUE) break; if (var->pkt.dts == AV_NOPTS_VALUE) { c->seek_timestamp = AV_NOPTS_VALUE; break; } st = var->ctx->streams[var->pkt.stream_index]; ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE, st->time_base.den, AV_ROUND_DOWN) - c->seek_timestamp; if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY || var->pkt.flags & AV_PKT_FLAG_KEY)) { c->seek_timestamp = AV_NOPTS_VALUE; break; } } } /* Check if this stream has the packet with the lowest dts */ if (var->pkt.data) { if(minvariant < 0) { minvariant = i; } else { struct variant *minvar = c->variants[minvariant]; int64_t dts = var->pkt.dts; int64_t mindts = minvar->pkt.dts; AVStream *st = var->ctx->streams[ var->pkt.stream_index]; AVStream *minst= minvar->ctx->streams[minvar->pkt.stream_index]; if( st->start_time != AV_NOPTS_VALUE) dts -= st->start_time; if(minst->start_time != AV_NOPTS_VALUE) mindts -= minst->start_time; if (av_compare_ts(dts, st->time_base, mindts, minst->time_base) < 0) minvariant = i; } } } if (c->end_of_segment) { if (recheck_discard_flags(s, 0)) goto start; } /* If we got a packet, return it */ if (minvariant >= 0) { *pkt = c->variants[minvariant]->pkt; pkt->stream_index += c->variants[minvariant]->stream_offset; reset_packet(&c->variants[minvariant]->pkt); return 0; } return AVERROR_EOF; }
static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) { HLSContext *c = s->priv_data; int ret, i, minvariant = -1; if (c->first_packet) { recheck_discard_flags(s, 1); c->first_packet = 0; } // __android_log_print(ANDROID_LOG_VERBOSE, TAG, "hls_read_packet,n_variants = %d", c->n_variants); start: c->end_of_segment = 0; for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; /* Make sure we've got one buffered packet from each open variant * stream */ if (var->needed && !var->pkt.data) { while (1) { int64_t ts_diff; AVStream *st; ret = av_read_frame(var->ctx, &var->pkt); if (ret < 0) { if (!url_feof(&var->pb)) return ret; reset_packet(&var->pkt); break; } #if 0 // Modify By Yen For Test else { if (c->first_timestamp == AV_NOPTS_VALUE) c->first_timestamp = var->pkt.dts; } #endif if (c->seek_timestamp == AV_NOPTS_VALUE) { break; } if (var->pkt.dts == AV_NOPTS_VALUE) { c->seek_timestamp = AV_NOPTS_VALUE; break; } st = var->ctx->streams[var->pkt.stream_index]; ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE, st->time_base.den, AV_ROUND_DOWN) - c->seek_timestamp; if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY || var->pkt.flags & AV_PKT_FLAG_KEY)) { c->seek_timestamp = AV_NOPTS_VALUE; break; } } } /* Check if this stream has the packet with the lowest dts */ if (var->pkt.data) { if (minvariant < 0 || var->pkt.dts < c->variants[minvariant]->pkt.dts) minvariant = i; } } if (c->end_of_segment) { if (recheck_discard_flags(s, 0)) goto start; } /* If we got a packet, return it */ if (minvariant >= 0) { *pkt = c->variants[minvariant]->pkt; pkt->stream_index += c->variants[minvariant]->stream_offset; reset_packet(&c->variants[minvariant]->pkt); return 0; } return AVERROR_EOF; }
/*---------------------------------------------------------------------------*/ static int tcp_input(struct tcp_socket *s, void *ptr, const uint8_t *input_data_ptr, int input_data_len) { struct mqtt_connection *conn = ptr; uint32_t pos = 0; uint32_t copy_bytes = 0; uint8_t byte; if(input_data_len == 0) { return 0; } if(conn->in_packet.packet_received) { reset_packet(&conn->in_packet); } DBG("tcp_input with %i bytes of data:\n", input_data_len); /* Read the fixed header field, if we do not have it */ if(!conn->in_packet.fhdr) { conn->in_packet.fhdr = input_data_ptr[pos++]; conn->in_packet.byte_counter++; DBG("MQTT - Read VHDR '%02X'\n", conn->in_packet.fhdr); if(pos >= input_data_len) { return 0; } } /* Read the Remaining Length field, if we do not have it */ if(!conn->in_packet.has_remaining_length) { do { if(pos >= input_data_len) { return 0; } byte = input_data_ptr[pos++]; conn->in_packet.byte_counter++; conn->in_packet.remaining_length_bytes++; DBG("MQTT - Read Remaining Length byte\n"); if(conn->in_packet.byte_counter > 5) { call_event(conn, MQTT_EVENT_ERROR, NULL); DBG("Received more then 4 byte 'remaining lenght'."); return 0; } conn->in_packet.remaining_length += (byte & 127) * conn->in_packet.remaining_multiplier; conn->in_packet.remaining_multiplier *= 128; } while((byte & 128) != 0); DBG("MQTT - Finished reading remaining length byte\n"); conn->in_packet.has_remaining_length = 1; } /* * Check for unsupported payload length. Will read all incoming data from the * server in any case and then reset the packet. * * TODO: Decide if we, for example, want to disconnect instead. */ if((conn->in_packet.remaining_length > MQTT_INPUT_BUFF_SIZE) && (conn->in_packet.fhdr & 0xF0) != MQTT_FHDR_MSG_TYPE_PUBLISH) { PRINTF("MQTT - Error, unsupported payload size for non-PUBLISH message\n"); conn->in_packet.byte_counter += input_data_len; if(conn->in_packet.byte_counter >= (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { conn->in_packet.packet_received = 1; } return 0; } /* * Supported payload, reads out both VHDR and Payload of all packets. * * Note: There will always be at least one byte left to read when we enter * this loop. */ while(conn->in_packet.byte_counter < (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { if((conn->in_packet.fhdr & 0xF0) == MQTT_FHDR_MSG_TYPE_PUBLISH && conn->in_packet.topic_received == 0) { parse_publish_vhdr(conn, &pos, input_data_ptr, input_data_len); } /* Read in as much as we can into the packet payload */ copy_bytes = MIN(input_data_len - pos, MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos); DBG("- Copied %lu payload bytes\n", copy_bytes); memcpy(&conn->in_packet.payload[conn->in_packet.payload_pos], &input_data_ptr[pos], copy_bytes); conn->in_packet.byte_counter += copy_bytes; conn->in_packet.payload_pos += copy_bytes; pos += copy_bytes; uint8_t i; DBG("MQTT - Copied bytes: \n"); for(i = 0; i < copy_bytes; i++) { DBG("%02X ", conn->in_packet.payload[i]); } DBG("\n"); /* Full buffer, shall only happen to PUBLISH messages. */ if(MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos == 0) { conn->in_publish_msg.payload_chunk = conn->in_packet.payload; conn->in_publish_msg.payload_chunk_length = MQTT_INPUT_BUFF_SIZE; conn->in_publish_msg.payload_left -= MQTT_INPUT_BUFF_SIZE; handle_publish(conn); conn->in_publish_msg.payload_chunk = conn->in_packet.payload; conn->in_packet.payload_pos = 0; } if(pos >= input_data_len && (conn->in_packet.byte_counter < (MQTT_FHDR_SIZE + conn->in_packet.remaining_length))) { return 0; } } /* Debug information */ DBG("\n"); /* Take care of input */ DBG("MQTT - Finished reading packet!\n"); /* What to return? */ DBG("MQTT - total data was %i bytes of data. \n", (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)); /* Handle packet here. */ switch(conn->in_packet.fhdr & 0xF0) { case MQTT_FHDR_MSG_TYPE_CONNACK: handle_connack(conn); break; case MQTT_FHDR_MSG_TYPE_PUBLISH: /* This is the only or the last chunk of publish payload */ conn->in_publish_msg.payload_chunk = conn->in_packet.payload; conn->in_publish_msg.payload_chunk_length = conn->in_packet.payload_pos; conn->in_publish_msg.payload_left = 0; handle_publish(conn); break; case MQTT_FHDR_MSG_TYPE_PUBACK: handle_puback(conn); break; case MQTT_FHDR_MSG_TYPE_SUBACK: handle_suback(conn); break; case MQTT_FHDR_MSG_TYPE_UNSUBACK: handle_unsuback(conn); break; case MQTT_FHDR_MSG_TYPE_PINGRESP: handle_pingresp(conn); break; /* QoS 2 not implemented yet */ case MQTT_FHDR_MSG_TYPE_PUBREC: case MQTT_FHDR_MSG_TYPE_PUBREL: case MQTT_FHDR_MSG_TYPE_PUBCOMP: call_event(conn, MQTT_EVENT_NOT_IMPLEMENTED_ERROR, NULL); PRINTF("MQTT - Got unhandled MQTT Message Type '%i'", (conn->in_packet.fhdr & 0xF0)); break; default: /* All server-only message */ PRINTF("MQTT - Got MQTT Message Type '%i'", (conn->in_packet.fhdr & 0xF0)); break; } conn->in_packet.packet_received = 1; return 0; }
static int hls_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { HLSContext *c = s->priv_data; int i, j, ret; //__android_log_print(ANDROID_LOG_INFO, TAG,"func:%s line:%d timestamp = %f", __func__, __LINE__, // (double)(timestamp/1000000.0)); if ((flags & AVSEEK_FLAG_BYTE) #if 0 // modified by yen for TSTV || !c->variants[0]->finished #endif ) { return AVERROR(ENOSYS); } c->seek_flags = flags; c->seek_timestamp = stream_index < 0 ? timestamp : av_rescale_rnd(timestamp, AV_TIME_BASE, s->streams[stream_index]->time_base.den, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); #if 0 // modified by yen for TSTV if (s->duration < c->seek_timestamp) { c->seek_timestamp = AV_NOPTS_VALUE; //__android_log_print(ANDROID_LOG_VERBOSE, TAG, "hls_read_seek,return err 2"); return AVERROR(EIO); } #endif ret = AVERROR(EIO); for (i = 0; i < c->n_variants; i++) { /* Reset reading */ struct variant *var = c->variants[i]; int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 : av_rescale_rnd(c->first_timestamp, 1, // modified by yen from 1->AV_TIME_BASE (second->microsecond) stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); if (var->input) { ffurl_close(var->input); var->input = NULL; } av_free_packet(&var->pkt); reset_packet(&var->pkt); var->pb.eof_reached = 0; /* Clear any buffered data */ var->pb.buf_end = var->pb.buf_ptr = var->pb.buffer; /* Reset the pos, to let the mpegts demuxer know we've seeked. */ var->pb.pos = 0; //__android_log_print(ANDROID_LOG_WARN, TAG, "hls_read_seek POS,first_timestamp:%f,seek_timestamp:%f,pos:%f", // (double)(c->first_timestamp/1000000.0),(double)(c->seek_timestamp/AV_TIME_BASE),(double)(pos/1000000.0)); /** * Yen: if seek_timestamp lower then position that we set position = start_seq_no * if seek_timestamp biger then duration that we set position = last_seq_no - 3 */ // if(c->seek_timestamp == 0) { // var->cur_seq_no = var->start_seq_no; // ret = 0; //// __android_log_print(ANDROID_LOG_VERBOSE, TAG, "hls_read_seek 0,ok,seek_timestamp:%f,pos:%f,max:%f", //// (double)c->seek_timestamp/1000000.0,(double)pos/1000000.0,(double)((pos + (var->segments[j]->duration*AV_TIME_BASE))/AV_TIME_BASE)); // // break; // } // // if(c->seek_timestamp <= pos) { // var->cur_seq_no = var->start_seq_no; // ret = 0; //// __android_log_print(ANDROID_LOG_VERBOSE, TAG, "hls_read_seek 1,ok,seek_timestamp:%f,pos:%f,max:%f", //// (double)c->seek_timestamp/1000000.0,(double)pos/1000000.0,(double)((pos + (var->segments[j]->duration*AV_TIME_BASE))/AV_TIME_BASE)); // // break; // } // else if(c->seek_timestamp >= (pos + s->duration)) { // var->cur_seq_no = var->start_seq_no + var->n_segments - 3; // ret = 0; //// __android_log_print(ANDROID_LOG_VERBOSE, TAG, "hls_read_seek 2,ok,seek_timestamp:%f,pos:%f,max:%f,cur_seq_no:%d,n_segments:%d", //// (double)c->seek_timestamp/1000000.0,(double)pos/1000000.0,(double)((pos + (s->duration))/AV_TIME_BASE),var->cur_seq_no,var->n_segments); // // break; // } /* Locate the segment that contains the target timestamp */ for (j = 0; j < var->n_segments; j++) { if (c->seek_timestamp > pos & c->seek_timestamp < (pos + (var->segments[j]->duration*AV_TIME_BASE))) { // modified by yen second->microsecond (*AV_TIME_BASE) var->cur_seq_no = var->start_seq_no + j; ret = 0; // __android_log_print(ANDROID_LOG_VERBOSE, TAG, "hls_read_seek 3,ok,seek_timestamp:%f,pos:%f,max:%f,cur_seq_no:%d,n_segments:%d", // (double)c->seek_timestamp/1000000.0,(double)pos/1000000.0,(double)((pos + (var->segments[j]->duration*AV_TIME_BASE))/AV_TIME_BASE),var->cur_seq_no,var->n_segments); break; } pos += var->segments[j]->duration*AV_TIME_BASE; // modified by yen same as up // __android_log_print(ANDROID_LOG_VERBOSE, TAG, "hls_read_seek,err,seek_timestamp:%f,pos:%f,max:%f,duration:%d", // (double)c->seek_timestamp/1000000.0,(double)pos/1000000.0,(double)((pos + (var->segments[j]->duration*AV_TIME_BASE))/AV_TIME_BASE),var->segments[j]->duration); } // if (ret) // c->seek_timestamp = AV_NOPTS_VALUE; } return ret; }
/*---------------------------------------------------------------------------*/ static PT_THREAD(publish_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending publish message! topic %s topic_length %i\n", conn->out_packet.topic, conn->out_packet.topic_length); DBG("MQTT - Buffer space is %i \n", &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_PUBLISH | conn->out_packet.qos << 1; if(conn->out_packet.retain == MQTT_RETAIN_ON) { conn->out_packet.fhdr |= MQTT_FHDR_RETAIN_FLAG; } conn->out_packet.remaining_length = MQTT_STRING_LEN_SIZE + conn->out_packet.topic_length + conn->out_packet.payload_size; if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { conn->out_packet.remaining_length += MQTT_MID_SIZE; } encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); PRINTF("MQTT - Error, remaining length > 4 bytes\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); /* Write Variable Header */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, conn->out_packet.topic_length); if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); } /* Write Payload */ PT_MQTT_WRITE_BYTES(conn, conn->out_packet.payload, conn->out_packet.payload_size); send_out_buffer(conn); timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); /* * If QoS is zero then wait until the message has been sent, since there is * no ACK to wait for. * * Also notify the app will not be notified via PUBACK or PUBCOMP */ if(conn->out_packet.qos == 0) { process_post(conn->app_process, mqtt_update_event, NULL); } else if(conn->out_packet.qos == 1) { /* Wait for PUBACK */ reset_packet(&conn->in_packet); PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || timer_expired(&conn->t)); if(timer_expired(&conn->t)) { DBG("Timeout waiting for PUBACK\n"); } if(conn->in_packet.mid != conn->out_packet.mid) { DBG("MQTT - Warning, got PUBACK with none matching MID. Currently there " "is no support for several concurrent PUBLISH messages.\n"); } } else if(conn->out_packet.qos == 2) { DBG("MQTT - QoS not implemented yet.\n"); /* Should wait for PUBREC, send PUBREL and then wait for PUBCOMP */ } reset_packet(&conn->in_packet); /* This is clear after the entire transaction is complete */ conn->out_queue_full = 0; DBG("MQTT - Publish Enqueued\n"); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(unsubscribe_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending unsubscribe message on topic %s topic_length %i\n", conn->out_packet.topic, conn->out_packet.topic_length); DBG("MQTT - Buffer space is %i \n", &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_UNSUBSCRIBE | MQTT_FHDR_QOS_LEVEL_1; conn->out_packet.remaining_length = MQTT_MID_SIZE + MQTT_STRING_LEN_SIZE + conn->out_packet.topic_length; encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); PRINTF("MQTT - Error, remaining length > 4 bytes\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); /* Write Variable Header */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); /* Write Payload */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, conn->out_packet.topic_length); /* Send out buffer */ send_out_buffer(conn); timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); /* Wait for UNSUBACK */ reset_packet(&conn->in_packet); PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || timer_expired(&conn->t)); if(timer_expired(&conn->t)) { DBG("Timeout waiting for UNSUBACK\n"); } reset_packet(&conn->in_packet); /* This is clear after the entire transaction is complete */ conn->out_queue_full = 0; DBG("MQTT - Done writing subscribe message to out buffer!\n"); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(connect_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending CONNECT message...\n"); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT; conn->out_packet.remaining_length = 0; conn->out_packet.remaining_length += MQTT_CONNECT_VHDR_FLAGS_SIZE; conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message); encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); PRINTF("MQTT - Error, remaining length > 4 bytes\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); PT_MQTT_WRITE_BYTE(conn, 0); PT_MQTT_WRITE_BYTE(conn, 6); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)MQTT_PROTOCOL_NAME, 6); PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION); PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF)); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->client_id.string, conn->client_id.length); if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.topic.string, conn->will.topic.length); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.message.string, conn->will.message.length); DBG("MQTT - Setting will topic to '%s' %u bytes and message to '%s' %u bytes\n", conn->will.topic.string, conn->will.topic.length, conn->will.message.string, conn->will.message.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->credentials.username.string, conn->credentials.username.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->credentials.password.string, conn->credentials.password.length); } /* Send out buffer */ send_out_buffer(conn); conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER; timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); /* Wait for CONNACK */ reset_packet(&conn->in_packet); PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || timer_expired(&conn->t)); if(timer_expired(&conn->t)) { DBG("Timeout waiting for CONNACK\n"); /* We stick to the letter of the spec here: Tear the connection down */ mqtt_disconnect(conn); } reset_packet(&conn->in_packet); DBG("MQTT - Done sending CONNECT\n"); #if DEBUG_MQTT == 1 DBG("MQTT - CONNECT message sent: \n"); uint16_t i; for(i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++) { DBG("%02X ", conn->out_buffer[i]); } DBG("\n"); #endif PT_END(pt); }
static int applehttp_read_packet(AVFormatContext *s, AVPacket *pkt) { AppleHTTPContext *c = s->priv_data; int ret, i, minvariant = -1, first = 1, needed = 0, changed = 0, variants = 0; /* Recheck the discard flags - which streams are desired at the moment */ for (i = 0; i < c->n_variants; i++) c->variants[i]->needed = 0; for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; struct variant *var = c->variants[s->streams[i]->id]; if (st->discard < AVDISCARD_ALL) { var->needed = 1; needed++; } /* Copy the discard flag to the chained demuxer, to indicate which * streams are desired. */ var->ctx->streams[i - var->stream_offset]->discard = st->discard; } if (!needed) return AVERROR_EOF; start: for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; /* Close unneeded streams, open newly requested streams */ if (var->pb && !var->needed) { av_log(s, AV_LOG_DEBUG, "Closing variant stream %d, no longer needed\n", i); av_free_packet(&var->pkt); reset_packet(&var->pkt); url_fclose(var->pb); var->pb = NULL; changed = 1; } else if (!var->pb && var->needed) { if (first) av_log(s, AV_LOG_DEBUG, "Opening variant stream %d\n", i); if (first && !c->finished) if ((ret = parse_playlist(c, var->url, var, NULL)) < 0) return ret; ret = open_variant(c, var, first); if (ret < 0) return ret; changed = 1; } /* Count the number of open variants */ if (var->pb) variants++; /* Make sure we've got one buffered packet from each open variant * stream */ if (var->pb && !var->pkt.data) { ret = av_read_frame(var->ctx, &var->pkt); if (ret < 0) { if (!url_feof(var->pb)) return ret; reset_packet(&var->pkt); } } /* Check if this stream has the packet with the lowest dts */ if (var->pkt.data) { if (minvariant < 0 || var->pkt.dts < c->variants[minvariant]->pkt.dts) minvariant = i; } } if (first && changed) av_log(s, AV_LOG_INFO, "Receiving %d variant streams\n", variants); /* If we got a packet, return it */ if (minvariant >= 0) { *pkt = c->variants[minvariant]->pkt; pkt->stream_index += c->variants[minvariant]->stream_offset; reset_packet(&c->variants[minvariant]->pkt); c->last_packet_dts = pkt->dts; return 0; } /* No more packets - eof reached in all variant streams, close the * current segments. */ for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; if (var->pb) { url_fclose(var->pb); var->pb = NULL; } } /* Indicate that we're opening the next segment, not opening a new * variant stream in parallel, so we shouldn't try to skip ahead. */ first = 0; c->cur_seq_no++; reload: if (!c->finished) { /* If this is a live stream and target_duration has elapsed since * the last playlist reload, reload the variant playlists now. */ int64_t now = av_gettime(); if (now - c->last_load_time >= c->target_duration*1000000) { c->max_start_seq = 0; c->min_end_seq = INT_MAX; for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; if (var->needed) { if ((ret = parse_playlist(c, var->url, var, NULL)) < 0) return ret; c->max_start_seq = FFMAX(c->max_start_seq, var->start_seq_no); c->min_end_seq = FFMIN(c->min_end_seq, var->start_seq_no + var->n_segments); } } } } if (c->cur_seq_no < c->max_start_seq) { av_log(NULL, AV_LOG_WARNING, "skipping %d segments ahead, expired from playlists\n", c->max_start_seq - c->cur_seq_no); c->cur_seq_no = c->max_start_seq; } /* If more segments exit, open the next one */ if (c->cur_seq_no < c->min_end_seq) goto start; /* We've reached the end of the playlists - return eof if this is a * non-live stream, wait until the next playlist reload if it is live. */ if (c->finished) return AVERROR_EOF; while (av_gettime() - c->last_load_time < c->target_duration*1000000) { if (url_interrupt_cb()) return AVERROR(EINTR); usleep(100*1000); } /* Enough time has elapsed since the last reload */ goto reload; }
static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) { HLSContext *c = s->priv_data; int ret, i, minplaylist = -1; if (c->first_packet) { recheck_discard_flags(s, 1); c->first_packet = 0; } start: c->end_of_segment = 0; for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; /* Make sure we've got one buffered packet from each open playlist * stream */ if (pls->needed && !pls->pkt.data) { while (1) { int64_t ts_diff; AVStream *st; ret = av_read_frame(pls->ctx, &pls->pkt); if (ret < 0) { if (!url_feof(&pls->pb) && ret != AVERROR_EOF) return ret; reset_packet(&pls->pkt); break; } else { if (c->first_timestamp == AV_NOPTS_VALUE && pls->pkt.dts != AV_NOPTS_VALUE) c->first_timestamp = av_rescale_q(pls->pkt.dts, pls->ctx->streams[pls->pkt.stream_index]->time_base, AV_TIME_BASE_Q); } if (c->seek_timestamp == AV_NOPTS_VALUE) break; if (pls->pkt.dts == AV_NOPTS_VALUE) { c->seek_timestamp = AV_NOPTS_VALUE; break; } st = pls->ctx->streams[pls->pkt.stream_index]; ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE, st->time_base.den, AV_ROUND_DOWN) - c->seek_timestamp; if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY || pls->pkt.flags & AV_PKT_FLAG_KEY)) { c->seek_timestamp = AV_NOPTS_VALUE; break; } av_free_packet(&pls->pkt); reset_packet(&pls->pkt); } } /* Check if this stream still is on an earlier segment number, or * has the packet with the lowest dts */ if (pls->pkt.data) { struct playlist *minpls = minplaylist < 0 ? NULL : c->playlists[minplaylist]; if (minplaylist < 0 || pls->cur_seq_no < minpls->cur_seq_no) { minplaylist = i; } else if (pls->cur_seq_no == minpls->cur_seq_no) { int64_t dts = pls->pkt.dts; int64_t mindts = minpls->pkt.dts; AVStream *st = pls->ctx->streams[pls->pkt.stream_index]; AVStream *minst = minpls->ctx->streams[minpls->pkt.stream_index]; if (dts == AV_NOPTS_VALUE) { minplaylist = i; } else if (mindts != AV_NOPTS_VALUE) { if (st->start_time != AV_NOPTS_VALUE) dts -= st->start_time; if (minst->start_time != AV_NOPTS_VALUE) mindts -= minst->start_time; if (av_compare_ts(dts, st->time_base, mindts, minst->time_base) < 0) minplaylist = i; } } } } if (c->end_of_segment) { if (recheck_discard_flags(s, 0)) goto start; } /* If we got a packet, return it */ if (minplaylist >= 0) { *pkt = c->playlists[minplaylist]->pkt; pkt->stream_index += c->playlists[minplaylist]->stream_offset; reset_packet(&c->playlists[minplaylist]->pkt); return 0; } return AVERROR_EOF; }