46 #define THROTTLE_BYTES (3 * 1024 * 1024 - 262144) 49 #define INVALID_TIMESTAMP 0xffffffff 50 #define SYNC_BYTE 0x47 51 #define SYNC_COUNT_ACCEPT 20 52 #define SYNC_BUFFER_SIZE (STMR_TS_PACKET_SIZE * SYNC_COUNT_ACCEPT) 53 #define SYNC_COUNT_MIN_ACCEPT (SYNC_COUNT_ACCEPT / 2) 58 #define GOOD_MAGIC 0xdeadbeef 59 #define BAD_MAGIC 0xfefefefe 60 #define SET_MAGIC(r) do { r->magic = GOOD_MAGIC; } while (0) 61 #define VERIFY_MAGIC(r) assert(r->magic == GOOD_MAGIC) 62 #define CLEAR_MAGIC(r) do { r->magic = BAD_MAGIC; } while (0) 65 #define VERIFY_MAGIC(r) 66 #define CLEAR_MAGIC(r) 70 #define PDBG(x) TRACE(TICS, x) 92 U8BIT section[STMR_MAX_PSI_SECTION];
97 U32BIT firstTimestamp;
118 HttpRequest_t handle;
142 enum SyncState syncState;
143 U8BIT syncBuffer[SYNC_BUFFER_SIZE];
144 U16BIT syncBufferPos;
146 U32BIT bytesPerSecond;
147 BOOLEAN knownBitrate;
153 U32BIT targetBitrate;
157 U8BIT partialData[STMR_TS_PACKET_SIZE];
158 U16BIT partialDataLength;
172 static BOOLEAN HeaderCallback(
void *userdata, U32BIT downloadId,
176 static BOOLEAN ContentCallback(
void *userdata, U32BIT downloadId,
180 static BOOLEAN HandleData(
DownloadRequest *request, U8BIT *data, U32BIT len);
181 static BOOLEAN StoreItem(
DownloadRequest *request, U8BIT *data, U32BIT len,
187 static BOOLEAN ProcessPacket(U8BIT *packet,
PsiInfo *psiInfo,
189 static BOOLEAN BuildSection(U8BIT *packet, U8BIT *section, U16BIT *offset);
190 static void HandlePatSection(
PsiInfo *psiInfo);
191 static void HandlePmtSection(
PsiInfo *psiInfo);
192 static BOOLEAN HandlePcrPacket(U8BIT *packet, U32BIT *timestamp);
193 static void NotifyHeadersDone(U32BIT downloadId,S32BIT code);
194 static void NotifyDownloadComplete(U32BIT downloadId,E_HttpStatus status,S32BIT code);
195 static BOOLEAN IsValidSection(U8BIT *section);
216 char rangeBuffer[MHEG5_MAX_RANGE_BUFFER];
221 request = MHEG5getMem(
sizeof *request);
229 request->requestId = requestId;
231 request->https = FALSE;
232 if (memcmp(url,
"https://", 8) == 0)
234 request->https = TRUE;
237 request->rangeFrom = rangeFrom;
238 request->rangeTo = rangeTo;
239 request->lastRequest = lastRequest;
241 request->handle = NULL;
243 request->status = HTTP_STATUS_OTHER_ERROR;
245 ULL_SetInvalid(request->contentLength);
246 ULL_Set32(request->bytesReceived, 0);
247 ULL_SetInvalid(request->bytesExpected);
249 request->processing = FALSE;
250 request->stopped = FALSE;
252 request->keyLocation.len = 0;
253 request->keyLocation.data = NULL;
254 request->keys.num_pids = 0;
255 request->keys.pid_info = 0;
257 request->syncState = SYNC_ACCUM;
258 request->syncBufferPos = 0;
260 request->bytesPerSecond = 0;
261 request->knownBitrate = FALSE;
262 request->timestamp = 0;
264 request->throttled = FALSE;
265 request->targetBitrate = 0;
266 ULL_Set32(request->throttledBytes, 0);
269 request->partialDataLength = 0;
271 request->psiInfo.state = PSI_STATE_PAT;
272 request->psiInfo.offset = 0;
273 request->psiInfo.pmt_pid = 0xffff;
274 request->psiInfo.pcr_pid = 0xffff;
275 request->psiInfo.firstTimestamp = INVALID_TIMESTAMP;
276 ULL_SetInvalid(request->psiInfo.firstPosition);
277 request->psiInfo.prevTimestamp = INVALID_TIMESTAMP;
278 request->psiInfo.lastTimestamp = INVALID_TIMESTAMP;
279 ULL_SetInvalid(request->psiInfo.lastPosition);
281 request->next = downloadRequestList;
282 downloadRequestList = request;
284 ULL_Itoa(rangeFrom, rangeBuffer);
285 strcat(rangeBuffer,
"-");
286 if (ULL_IsValid(rangeTo))
288 ULL_Itoa(rangeTo, &rangeBuffer[strlen(rangeBuffer)]);
292 (U8BIT *)rangeBuffer,
297 if (request->handle != NULL)
299 downloadId = request->downloadId;
304 MHEG5freeMem(request);
321 request = FindRequestById(downloadId);
324 VERIFY_MAGIC(request);
326 assert(request->handle != NULL);
340 U8BIT *redirectUrl = NULL;
342 request = FindRequestById(downloadId);
345 VERIFY_MAGIC(request);
347 PDBG((
"id=%d",downloadId));
363 request = FindRequestById(downloadId);
370 result = IsPositionPartial(request);
374 *position = request->rangeFrom;
375 ULL_Add(*position,request->bytesReceived);
379 ULL_Set32((*position),0);
398 request = FindRequestById(downloadId);
401 VERIFY_MAGIC(request);
403 contentLength = request->contentLength;
405 return contentLength;
420 request = FindRequestById(downloadId);
423 VERIFY_MAGIC(request);
425 if (request->bytesPerSecond > 0)
427 *bytesPerSecond = request->bytesPerSecond;
450 request = FindRequestById(downloadId);
453 VERIFY_MAGIC(request);
455 if ((request->keys.num_pids > 0) || (request->keyLocation.len > 0))
457 if (keys->num_pids > 0)
460 MHEG5freeMem(keys->pid_info);
462 keys->pid_info = NULL;
465 if (keyLocation->len > 0)
471 if (request->keys.num_pids > 0)
474 *keys = request->keys;
477 request->keys.num_pids = 0;
478 request->keys.pid_info = NULL;
481 if (request->keyLocation.len > 0)
484 *keyLocation = request->keyLocation;
487 request->keyLocation.len = 0;
488 request->keyLocation.data = NULL;
504 BOOLEAN found = FALSE;
506 request = FindRequestById(downloadId);
509 VERIFY_MAGIC(request);
511 if (request->psiInfo.state == PSI_STATE_PCR)
514 memcpy(pmt, request->psiInfo.section, STMR_MAX_PSI_SECTION);
531 request = downloadRequestList;
534 VERIFY_MAGIC(request);
536 if (!request->processing)
538 DBG((
"Download: Resuming connection"));
553 request = downloadRequestList;
556 VERIFY_MAGIC(request);
558 DBG((
"Download: Clearing throttling"));
559 request->timestamp = 0;
562 request->throttled = FALSE;
563 request->targetBitrate = 0;
564 ULL_Set32(request->throttledBytes, 0);
567 request->psiInfo.firstTimestamp = INVALID_TIMESTAMP;
568 ULL_SetInvalid(request->psiInfo.firstPosition);
569 request->psiInfo.lastTimestamp = INVALID_TIMESTAMP;
570 ULL_SetInvalid(request->psiInfo.lastPosition);
572 if (!request->processing)
588 request = FindRequestById(downloadId);
591 VERIFY_MAGIC(request);
593 if (request->handle != NULL)
613 request = FindRequestById(downloadId);
616 VERIFY_MAGIC(request);
618 request->stopped = TRUE;
631 pRequest = &downloadRequestList;
632 while (*pRequest != NULL)
635 if (request->downloadId == downloadId)
637 VERIFY_MAGIC(request);
639 *pRequest = request->next;
641 if (request->handle != NULL)
645 if (request->keys.num_pids > 0)
647 MHEG5freeMem(request->keys.pid_info);
651 MHEG5freeMem(request);
657 pRequest = &request->next;
671 request = FindRequestById(downloadId);
674 VERIFY_MAGIC(request);
676 if (request->handle != NULL)
680 request->handle = NULL;
682 if (request->keys.num_pids > 0)
684 MHEG5freeMem(request->keys.pid_info);
685 request->keys.num_pids = 0;
686 request->keys.pid_info = 0;
699 char rangeBuffer[MHEG5_MAX_RANGE_BUFFER];
702 request = FindRequestById(downloadId);
705 VERIFY_MAGIC(request);
706 assert(request->handle == NULL);
707 assert(request->status == HTTP_STATUS_PARTIAL);
709 request->processing = FALSE;
710 request->partialDataLength = 0;
712 ULL_Add(request->rangeFrom, request->bytesReceived);
713 ULL_Set32(request->bytesReceived, 0);
715 ULL_SetInvalid(request->contentLength);
716 ULL_SetInvalid(request->bytesExpected);
718 ULL_Itoa(request->rangeFrom, rangeBuffer);
719 strcat(rangeBuffer,
"-");
720 if (ULL_IsValid(request->rangeTo))
722 ULL_Itoa(request->rangeTo, &rangeBuffer[strlen(rangeBuffer)]);
725 HeaderCallback, ContentCallback, downloadId, request);
743 request = downloadRequestList;
744 while (request != NULL && request->downloadId != downloadId)
746 request = request->next;
759 static BOOLEAN HeaderCallback(
void *userdata, U32BIT downloadId,
764 VERIFY_MAGIC(request);
766 if (response->data_len <= 2)
769 request->code = response->code;
772 DBG((
"Calling NotifyHeadersDone"));
773 NotifyHeadersDone(downloadId,response->code);
777 HandleHeaderData(request, response->data, response->data_len);
802 case HTTP_FIELD_CONTENT_LENGTH:
804 if (ULL_IsValid(contentLength) &&
805 !ULL_IsValid(request->contentLength))
807 request->contentLength = contentLength;
808 request->bytesExpected = contentLength;
810 PDBG((
"rangeFrom=%s",
ULL_ToString(request->rangeFrom)));
811 ULL_Add(request->contentLength, request->rangeFrom);
812 PDBG((
"total contentLength=%s",
ULL_ToString(request->contentLength)));
815 case HTTP_FIELD_CONTENT_RANGE:
817 if (ULL_IsValid(contentLength) && ULL_Compare(contentLength,request->rangeFrom) > 0)
819 request->contentLength = contentLength;
820 request->bytesExpected = contentLength;
822 PDBG((
"rangeFrom=%s",
ULL_ToString(request->rangeFrom)));
823 ULL_Sub(request->bytesExpected, request->rangeFrom);
824 PDBG((
"expected=%s",
ULL_ToString(request->bytesExpected)));
827 case HTTP_FIELD_X_KEYS:
828 if (request->keys.num_pids > 0)
830 MHEG5freeMem(request->keys.pid_info);
831 request->keys.pid_info = NULL;
832 request->keys.num_pids = 0;
836 case HTTP_FIELD_X_KEY_LOCATION:
840 case HTTP_FIELD_X_BYTES_PER_SECOND:
842 &request->knownBitrate);
845 case HTTP_FIELD_UNKNOWN:
857 static BOOLEAN ContentCallback(
void *userdata, U32BIT downloadId,
863 VERIFY_MAGIC(request);
864 assert(request->downloadId == downloadId);
867 if (response->status == HTTP_STATUS_WAIT)
869 if (request->code == 200 || request->code == 206)
873 handled = HandleStreamData(request, response->data,
875 if (handled && request->stopped)
877 PDBG((
"Pause, id=%d request has stopped",downloadId));
878 request->status = HTTP_STATUS_OK;
879 NotifyDownloadComplete(downloadId,HTTP_STATUS_OK,request->code);
889 request->status = HTTP_STATUS_OTHER_ERROR;
890 NotifyDownloadComplete(downloadId,HTTP_STATUS_OTHER_ERROR,0);
902 PDBG((
"response->status = %s",
903 response->status == HTTP_STATUS_OK ?
"HTTP_STATUS_OK" :
904 response->status == HTTP_STATUS_PARTIAL ?
"HTTP_STATUS_PARTIAL" :
905 response->status == HTTP_STATUS_SSL_ERROR ?
"HTTP_STATUS_SSL_ERROR" :
906 response->status == HTTP_STATUS_NETWORK_ERROR ?
"HTTP_STATUS_NETWORK_ERROR" :
907 response->status == HTTP_STATUS_TIMEOUT ?
"HTTP_STATUS_TIMEOUT" :
908 response->status == HTTP_STATUS_OTHER_ERROR ?
"HTTP_STATUS_OTHER_ERROR" :
910 PDBG((
"Download: request %d: finished, code=%ld len=%ld", downloadId,response->code,response->data_len));
911 if (response->code == 206 &&
912 (response->status == HTTP_STATUS_OK || response->status == HTTP_STATUS_TIMEOUT) &&
913 IsPositionPartial(request) )
915 response->status = HTTP_STATUS_PARTIAL;
917 request->status = response->status;
918 NotifyDownloadComplete(downloadId,response->status,response->code);
934 BOOLEAN handled = FALSE;
939 BOOLEAN queueData = TRUE;
941 if (request->throttled)
947 if (current > request->timestamp)
949 bytes = request->throttledBytes;
950 ULL_Sub32(bytes, THROTTLE_BYTES);
951 ULL_Add32(bytes, len);
953 ULL_Mul32(bytes, 1050);
954 ULL_Div32(bytes, (current - request->timestamp));
955 bitrate = ULL_Get32(bytes);
963 if (bitrate <= request->targetBitrate)
977 DBG((
"Download: Pausing connection"));
983 handled = HandleData(request, data, len);
987 ULL_Add32(request->throttledBytes, len);
993 DBG((
"Download: Pausing connection"));
996 request->processing = handled;
1000 static BOOLEAN FindSyncOffset( U8BIT *syncBuffer, U16BIT *pOffset )
1002 U16BIT offset, i, count, maxCount, bestOffset;
1005 for (offset = 0; offset != STMR_TS_PACKET_SIZE; offset++)
1008 for (i = offset; i != (SYNC_BUFFER_SIZE + offset); i += STMR_TS_PACKET_SIZE)
1010 count += (syncBuffer[i] == SYNC_BYTE);
1013 if (count == SYNC_COUNT_ACCEPT)
1019 if (count > maxCount)
1022 bestOffset = offset;
1026 if (maxCount >= SYNC_COUNT_MIN_ACCEPT)
1028 DBG((
"[sync] Found possible offset %d with count %d\n",
1029 bestOffset, maxCount));
1030 offset = bestOffset;
1032 if (offset == STMR_TS_PACKET_SIZE)
1037 DBG((
"[sync] Could not find sync offset"));
1041 for (i = 0; i < SYNC_BUFFER_SIZE; i++)
1043 DBG_PRINTF(
"%02x ", syncBuffer[i]);
1053 DBG((
"[sync] Found offset %d", offset));
1066 static BOOLEAN HandleData(
DownloadRequest *request, U8BIT *data, U32BIT len )
1068 U16BIT offset, origOffset;
1074 switch (request->syncState)
1077 origOffset = request->syncBufferPos;
1080 DBG((
"[sync] request->syncState == SYNC_ACCUM"));
1081 assert( origOffset < SYNC_BUFFER_SIZE );
1082 offset = SYNC_BUFFER_SIZE - origOffset;
1085 offset = (U16BIT)len;
1087 memcpy(request->syncBuffer + origOffset, data, offset);
1089 DBG((
"[sync] Updated request->syncBufferPos from %d to %d",
1090 request->syncBufferPos, request->syncBufferPos + offset));
1091 request->syncBufferPos += offset;
1093 if (request->syncBufferPos != SYNC_BUFFER_SIZE)
1100 DBG((
"[sync] request->SyncState == SYNC_ACCUM and enough data"));
1101 if (!FindSyncOffset( request->syncBuffer, &offset ))
1103 request->syncState = SYNC_FAILED;
1107 request->syncState = SYNC_FOUND;
1111 DBG((
"[sync] offset = %d", offset));
1114 ULL_Add32(request->bytesReceived, offset);
1116 if (offset == origOffset)
1120 else if (offset > origOffset)
1123 len -= offset - origOffset;
1124 data += offset - origOffset;
1129 if (!StoreItem(request, request->syncBuffer + offset, origOffset - offset, &item))
1136 (void)ProcessItem(item, &request->psiInfo);
1143 if (!StoreItem(request, data, len, &item))
1150 if (!ProcessItem(item, &request->psiInfo))
1152 request->syncState = SYNC_ACCUM;
1153 origOffset = request->partialDataLength;
1154 request->syncBufferPos = origOffset;
1155 if (origOffset != 0)
1157 memcpy(request->syncBuffer, request->partialData, origOffset);
1158 request->partialDataLength = 0;
1167 PDBG((
"syncState=%d",request->syncState));
1183 static BOOLEAN StoreItem(
DownloadRequest *request, U8BIT *data, U32BIT len,
1186 U32BIT totalLen, storeLen, partialLen, remainingLen;
1192 totalLen = len + request->partialDataLength;
1193 storeLen = totalLen - totalLen % STMR_TS_PACKET_SIZE;
1194 if (storeLen >= STMR_TS_PACKET_SIZE)
1196 partialLen = storeLen - request->partialDataLength;
1206 DBG((
"FAIL Q alloc for %d",storeLen));
1212 if (request->partialDataLength > 0)
1214 memcpy(item->data, request->partialData,
1215 request->partialDataLength);
1216 item->len += request->partialDataLength;
1220 memcpy(item->data + item->len, data, partialLen);
1221 item->len += partialLen;
1224 remainingLen = len - partialLen;
1225 if (remainingLen > 0)
1227 assert(remainingLen < STMR_TS_PACKET_SIZE);
1228 memcpy(request->partialData, data + partialLen,
1231 request->partialDataLength = (U16BIT)remainingLen;
1233 PDBG((
"Download: Inserting item(%d, %u + %u + %u)",
1234 request->downloadId, ULL_Get32(request->rangeFrom),
1235 ULL_Get32(request->bytesReceived),storeLen));
1237 item->position = request->bytesReceived;
1238 item->base = request->rangeFrom;
1239 item->downloadId = request->downloadId;
1240 item->timestamp = 0;
1242 ULL_Add32(request->bytesReceived, storeLen);
1243 if ((request->lastRequest) &&
1244 (ULL_IsEqual(request->bytesReceived,
1245 request->bytesExpected)))
1247 PDBG((
"expected=%s",
ULL_ToString(request->bytesExpected)));
1256 if (!request->throttled)
1258 CheckThrottling(request);
1270 memcpy(request->partialData + request->partialDataLength,
1272 request->partialDataLength += (U16BIT)len;
1290 if (!request->throttled)
1292 if (ULL_Get32(request->throttledBytes) >= THROTTLE_BYTES &&
1293 request->psiInfo.firstTimestamp != request->psiInfo.lastTimestamp)
1295 request->throttled = TRUE;
1297 bitrate = request->psiInfo.lastPosition;
1298 ULL_Sub(bitrate, request->psiInfo.firstPosition);
1299 ULL_Mul32(bitrate, 1200);
1300 ULL_Div32(bitrate, request->psiInfo.lastTimestamp - request->psiInfo.firstTimestamp);
1301 request->targetBitrate = ULL_Get32(bitrate);
1320 U32BIT remaining = item->len;
1321 U8BIT *packet = item->data;
1326 assert((remaining % STMR_TS_PACKET_SIZE) == 0);
1327 while (remaining != 0)
1329 if (packet[0] != SYNC_BYTE)
1331 PDBG((
"Need to find sync byte again"))
1335 if (ProcessPacket(packet, psiInfo, ×tamp))
1337 DBG((
"item=%p position=%s timestamp=%lu remaining=%d",item,
ULL_ToString(item->position),timestamp,remaining));
1338 if (psiInfo->firstTimestamp == INVALID_TIMESTAMP)
1340 psiInfo->firstTimestamp = timestamp;
1341 psiInfo->firstPosition = item->position;
1342 ULL_Add32(psiInfo->firstPosition, item->len);
1345 psiInfo->lastTimestamp = timestamp;
1346 psiInfo->lastPosition = item->position;
1348 assert(item->timestamp == 0);
1349 if (item->timestamp == 0)
1351 item->timestamp = timestamp;
1359 packet += STMR_TS_PACKET_SIZE;
1360 remaining -= STMR_TS_PACKET_SIZE;
1362 if (psiInfo->state == PSI_STATE_PCR && ok)
1365 remaining = item->len;
1366 remaining -= remaining % STMR_TS_PACKET_SIZE;
1367 packet = item->data + remaining;
1368 if (item->timestamp == 0)
1370 DBG((
"item=%p position=%s timestamp=%lu remaining=%d",item,
ULL_ToString(item->position),psiInfo->prevTimestamp,remaining));
1371 item->timestamp = psiInfo->prevTimestamp;
1373 while (remaining != 0)
1375 packet -= STMR_TS_PACKET_SIZE;
1376 remaining -= STMR_TS_PACKET_SIZE;
1377 pid = (packet[1] << 8 | packet[2]) & 0x1fff;
1378 if (pid == psiInfo->pcr_pid &&
1379 HandlePcrPacket(packet,×tamp))
1381 DBG((
"item=%p position=%s timestamp=%lu remaining=%d",item,
ULL_ToString(item->position),timestamp,remaining));
1382 psiInfo->prevTimestamp = timestamp;
1398 static BOOLEAN ProcessPacket(U8BIT *packet,
PsiInfo *psiInfo,
1407 pid = (packet[1] << 8 | packet[2]) & 0x1fff;
1409 switch (psiInfo->state)
1414 built = BuildSection(packet, psiInfo->section, &psiInfo->offset);
1417 if (psiInfo->section[0] == 0x00)
1419 HandlePatSection(psiInfo);
1421 psiInfo->offset = 0;
1426 if (pid == psiInfo->pmt_pid)
1428 built = BuildSection(packet, psiInfo->section, &psiInfo->offset);
1431 if (psiInfo->section[0] == 0x02)
1433 HandlePmtSection(psiInfo);
1435 psiInfo->offset = 0;
1440 if (pid == psiInfo->pcr_pid)
1442 found = HandlePcrPacket(packet, timestamp);
1457 static BOOLEAN BuildSection(U8BIT *packet, U8BIT *section, U16BIT *offset)
1459 U32BIT payload_start_indicator;
1460 U32BIT adaptation_field_control;
1463 U16BIT payload_length;
1468 payload_start_indicator = (packet[1] >> 6) & 0x1;
1469 adaptation_field_control = (packet[3] >> 4) & 0x3;
1470 if (adaptation_field_control >= 2)
1472 payload = packet + 5 + packet[4];
1473 payload_length = 188 - 5 - packet[4];
1477 payload = packet + 4;
1478 payload_length = 188 - 4;
1481 if (payload_start_indicator)
1483 pointer = payload[0];
1484 if (payload_length > 0)
1486 memcpy(section, payload + 1 + pointer, payload_length - 1);
1487 *offset = payload_length - 1;
1494 else if (*offset > 0)
1496 if (payload_length > 0)
1498 if (*offset + payload_length <= STMR_MAX_PSI_SECTION)
1500 memcpy(section + *offset, payload, payload_length);
1501 *offset += payload_length;
1513 U16BIT section_length;
1515 section_length = (section[1] << 8 | section[2]) & 0xfff;
1516 if (*offset >= section_length + 3)
1518 complete = IsValidSection(section);
1535 static void HandlePatSection(
PsiInfo *psiInfo)
1537 U8BIT *section = psiInfo->section;
1538 U16BIT section_length;
1540 U16BIT program_number;
1543 section_length = (section[1] << 8 | section[2]) & 0xfff;
1545 while (offset + 4 < section_length + 3)
1547 program_number = section[offset] << 8 | section[offset + 1];
1548 pmt_pid = (section[offset + 2] << 8 | section[offset + 3]) & 0x1fff;
1549 if (program_number != 0x0000)
1551 PDBG((
"program_number = %d, program_map_PID = %d",
1552 program_number, pmt_pid));
1553 psiInfo->pmt_pid = pmt_pid;
1554 psiInfo->state = PSI_STATE_PMT;
1567 static void HandlePmtSection(
PsiInfo *psiInfo)
1569 U8BIT *section = psiInfo->section;
1572 psiInfo->pcr_pid = (section[8] << 8 | section[9]) & 0x1fff;
1573 PDBG((
"PCR PID = %d", psiInfo->pcr_pid));
1575 psiInfo->state = PSI_STATE_PCR;
1585 static BOOLEAN HandlePcrPacket(U8BIT *packet, U32BIT *timestamp)
1587 S32BIT adaptation_field_control;
1588 S32BIT adaptation_field_length;
1599 adaptation_field_control = (packet[3] >> 4) & 0x3;
1600 if (adaptation_field_control >= 2)
1602 adaptation_field_length = packet[4];
1603 if (adaptation_field_length > 0)
1605 PCR_flag = (packet[5] >> 4) & 0x1;
1615 pcr_base_x = (packet[6] << 24 |
1619 pcr_base_y = packet[10] >> 7;
1631 *timestamp = (pcr_base_x / 45 +
1632 (2 * (pcr_base_x % 45) + pcr_base_y) / 90);
1647 static void NotifyHeadersDone(U32BIT downloadId,S32BIT code)
1653 event.data_type = DT_VALUE;
1654 event.data.streamer.requestId = downloadId;
1655 event.data.streamer.code = code;
1656 event.data.streamer.eventType = MHEG5_STREAMER_EVENT_HTTP_HEADERS_DONE;
1658 cqu_err =
VQ_PutMsg(&event, PRTY_NORMAL);
1659 if (cqu_err != MHERR_OK)
1661 PDBG((
"NotifyHeaders: Cannot generate event %d", cqu_err));
1670 static void NotifyDownloadComplete(U32BIT downloadId,E_HttpStatus status,S32BIT code)
1676 event.data_type = DT_VALUE;
1677 event.data.streamer.requestId = downloadId;
1678 event.data.streamer.status = status;
1679 event.data.streamer.code = code;
1680 event.data.streamer.eventType = MHEG5_STREAMER_EVENT_HTTP_DOWNLOAD_DONE;
1682 cqu_err =
VQ_PutMsg(&event, PRTY_NORMAL);
1683 if (cqu_err != MHERR_OK)
1685 PDBG((
"Download: Cannot send MHEG5_STREAMER_EVENT_HTTP_DOWNLOAD_DONE %d", cqu_err));
1689 static U32BIT crc_table[] = {
1690 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
1691 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
1692 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
1693 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
1694 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
1695 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
1696 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
1697 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
1698 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
1699 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
1700 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
1701 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
1702 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
1703 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
1704 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
1705 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
1706 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
1707 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
1708 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
1709 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
1710 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
1711 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
1712 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
1713 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
1714 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
1715 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
1716 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
1717 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
1718 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
1719 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
1720 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
1721 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
1722 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
1723 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
1724 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
1725 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
1726 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
1727 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
1728 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
1729 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
1730 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
1731 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
1732 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
1741 static BOOLEAN IsValidSection(U8BIT *section)
1743 U16BIT section_length;
1747 BOOLEAN valid = FALSE;
1749 section_length = (section[1] << 8 | section[2]) & 0xfff;
1751 crc_accum = 0xffffffffL;
1752 limit = section + section_length + 3;
1753 while (section < limit)
1755 idx = ((crc_accum >> 24) ^ (*section++)) & 0xff;
1756 crc_accum = ((crc_accum << 8) ^ crc_table[idx]) & 0xffffffffL;
1759 if (crc_accum == 0x00000000)
1770 BOOLEAN result = FALSE;
1771 VERIFY_MAGIC(request);
1772 left = request->bytesExpected;
1774 if (ULL_IsValid(left) && ULL_Compare(left,request->bytesReceived) > 0)
1776 ULL_Sub(left,request->bytesReceived);
1777 if (ULL_Get32(left) > 262144)
1779 PDBG((
"******** PARTIAL DOWNLOAD **** id=%d, left=%s",request->downloadId,
ULL_ToString(left)));
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
U64BIT MHEG5GetDownloadContentLength(U32BIT downloadId, U64BIT contentLength)
Return content length (in bytes) for download request. The content length may be: ...
E_MhegErr VQ_PutMsg(S_MhegMessage *pMsg, E_PRIORITY priority)
Post event or section message on queue. Copies data into queue.
U32BIT MHEG5GetUniqueId(void)
Return a unique ID. The ID is a non-zero 32-bit value. It is guaranteed to be unique for the first 0x...
void httpStartRequest(HttpRequest_t request)
Start an HTTP request. Everything related to the request is passed through the callback that was regi...
Manages the interface between MHEG5 Engine and the HTTP component.
void MHEG5ClearDownloadRequest(U32BIT downloadId)
Clear HTTP download request.
Common header internal to IC streamer.
void MHEG5CopyDownloadStreamKeyInfo(U32BIT downloadId, S_ICSKeys *keys, MHEG5String *keyLocation)
Copy any keys or key location that were obtained from the headers. If such keys or location exist...
BOOLEAN MHEG5GetDownloadPmt(U32BIT downloadId, U8BIT *pmt)
Return program map table (PMT) for download (if available). The table is provided as a complete secti...
void MHEG5ClearDownloadThrottling(void)
Clear information about throttling, causing the download to proceed at full speed (until throttling k...
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
void(* F_MSG_PROCESS)(void *data)
Function to Process voyager message.
BOOLEAN MHEG5DownloadPositionPartial(U32BIT downloadId, U64BIT *position)
Return what is current position of download request.
void MHEG5RenewDownloadRequest(U32BIT downloadId, char *url)
Renew HTTP download request.
void MHEG5StopDownloadRequestAsync(U32BIT downloadId)
Stop HTTP download request asynchronously. This function should be used when the caller wants to stop...
char * ULL_ToString(U64BIT val)
Convert 64 bit value to string (for debug purposes).
IC Streamer queue manager.
U8BIT * httpGetRequestRedirect(HttpRequest_t request)
Return the URL that the request is redirected to (valid only for response codes of 3xx)...
void MHEG5StopDownloadRequest(U32BIT downloadId)
Stop HTTP download request.
U32BIT MHEG5CreateDownloadRequest(U32BIT requestId, char *url, U64BIT rangeFrom, U64BIT rangeTo, BOOLEAN lastRequest)
Create HTTP download request.
void MHEG5StartDownloadRequest(U32BIT downloadId)
Start HTTP download request.
void httpStopRequest(HttpRequest_t request)
Stop an HTTP request. This function does not destroy the request; this is done using httpDestroyReque...
void MHEG5QueueInsertItem(MHEG5QueueItem *item)
Insert a queue item into the queue.
void httpResumeRequest(HttpRequest_t request)
Resume an HTTP request. A request can be paused by returning FALSE from the content callback to tell ...
MHEG5QueueItem * MHEG5QueueAllocItem(U32BIT requestId, U32BIT len)
Allocate a new queue item and initialise with request ID and block length.
void MHEG5CopyDownloadBitrate(U32BIT downloadId, U32BIT *bytesPerSecond)
Copy download bitrate that was obtained from the headers. If the X-BytesPerSecond header were not rec...
void httpDestroyRequest(HttpRequest_t request)
Destroy an HTTP request.
void MHEG5StreamerHandle(MHEG5StreamerEventParams_t *params)
Process an MHEG5StreamerEvent message The event is passed onto the streamer module for processing...
void MHEG5ResumeDownload(void)
Resume download of the active request. Download may or may not have been paused due to the buffer bei...
void MHEG5DestroyDownloadRequest(U32BIT downloadId)
Destroy HTTP download request.
HttpRequest_t httpCreateStreamRequest(U8BIT *url, U8BIT *range, HttpCallback_t header_callback, HttpCallback_t callback, U32BIT request_id, void *userdata)
Create an HTTP request for stream media.
IC Streamer download manager.
U8BIT * MHEG5GetDownloadRedirect(U32BIT downloadId)
Return the redirection URL for a request that was redirected (HTTP status 3xx).
Header file - Function prototypes for operating system.