MHEG5  18.9.0
MHEG5 Documentation
stmr_msp.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2010 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include <assert.h>
27 #include <string.h>
28 
29 #include "stb_os.h"
30 #include "http_interface.h"
31 #include "glue_memory.h"
32 #include "glue_queue.h"
33 
34 #include "mh5base.h"
35 #include "mh5profile.h"
36 #include "mh5streamer.h"
37 #include "stmr_msp.h"
38 #include "stmr_util.h"
39 #include "stmr_common.h"
40 
41 /*---constant definitions for this file--------------------------------------*/
42 
43 #define MAX_MEASURE_SIZE (0x7fffffff)
44 
45 
46 
47 #define USE_MAGIC
48 
49 #ifdef USE_MAGIC
50 #define GOOD_MAGIC 0xdeadbeef
51 #define BAD_MAGIC 0xfefefefe
52 #define SET_MAGIC(r) do { r->magic = GOOD_MAGIC; } while (0)
53 #define VERIFY_MAGIC(r) assert(r->magic == GOOD_MAGIC)
54 #define CLEAR_MAGIC(r) do { r->magic = BAD_MAGIC; } while (0)
55 #else
56 #define SET_MAGIC(r)
57 #define VERIFY_MAGIC(r)
58 #define CLEAR_MAGIC(r)
59 #endif
60 
61 #define DBG(x)
62 
63 
64 /*---local typedef structs for this file-------------------------------------*/
65 
66 typedef struct sMeasureRequest
67 {
68  /* Magic */
70 
71  /* Download ID */
73 
74  /* Request ID */
76 
77  /* HTTP handle */
79 
80  /* Response code and status */
83 
84  /* Measurement */
89 
90  /* Next request */
93 
94 /*---local function definitions----------------------------------------------*/
95 
96 /*---global function definitions---------------------------------------------*/
97 
98 static MeasureRequest* FindRequestById(U32BIT requestId);
99 static BOOLEAN HeaderCallback(void *userdata, U32BIT downloadId,
100  HttpResponse_t *response);
101 static BOOLEAN ContentCallback(void *userdata, U32BIT downloadId,
102  HttpResponse_t *response);
103 static BOOLEAN HandleMeasureData(MeasureRequest *request, U32BIT bytes);
104 static BOOLEAN HandleMeasureEnd(MeasureRequest *request,
105  HttpResponse_t *response);
106 
107 /*---local (static) variable declarations for this file----------------------*/
108 
109 static MeasureRequest *measureRequestList = NULL;
110 
111 
120 {
121  char rangeBuffer[MHEG5_MAX_RANGE_BUFFER];
122  MeasureRequest *request;
124 
125  downloadId = 0;
126  request = MHEG5getMem(sizeof *request);
127  if (request != NULL)
128  {
129  SET_MAGIC(request);
130 
131  /* Download ID is a unique ID */
132  request->downloadId = MHEG5GetUniqueId();
133 
134  request->requestId = requestId;
135 
136  request->handle = NULL;
137  request->code = 0;
138  request->status = HTTP_STATUS_OTHER_ERROR;
139 
140  request->startTime = 0;
141  request->finishTime = 0;
142 
143  request->next = measureRequestList;
144  measureRequestList = request;
145 
146  strcpy(rangeBuffer, "0-");
147  if (maxBytes > 0)
148  {
149  sprintf(&rangeBuffer[2], "%d", (int)maxBytes);
150  }
151  else
152  {
153  maxBytes = 0x7fffffff;
154  }
155 
156  ULL_Set32(request->receivedBytes, 0);
157  ULL_Set32(request->maxReceivedBytes, maxBytes);
158 
159  request->handle = httpCreateStreamRequest((U8BIT *)url,
160  (U8BIT *)rangeBuffer,
161  HeaderCallback,
162  ContentCallback,
163  request->downloadId,
164  request);
165  if (request->handle != NULL)
166  {
167  downloadId = request->downloadId;
168  }
169  else
170  {
171  /* Failed to create an HTTP request */
172  MHEG5freeMem(request);
173  request = NULL;
174  }
175  }
176 
177  return downloadId;
178 }
179 
186 {
187  MeasureRequest *request;
188 
189  request = FindRequestById(downloadId);
190  if (request != NULL)
191  {
192  VERIFY_MAGIC(request);
193 
194  assert(request->handle != NULL);
196  httpStartRequest(request->handle);
197  }
198 }
199 
206 {
207  MeasureRequest *request;
208  S32BIT code = 0;
209 
210  request = FindRequestById(downloadId);
211  if (request != NULL)
212  {
213  VERIFY_MAGIC(request);
214 
215  code = request->code;
216  }
217 
218  return code;
219 }
220 
227 {
228  MeasureRequest *request;
230 
231  request = FindRequestById(downloadId);
232  if (request != NULL)
233  {
234  VERIFY_MAGIC(request);
235 
236  status = request->status;
237  }
238 
239  return status;
240 }
241 
249 {
250  MeasureRequest *request;
251  U8BIT *redirectUrl = NULL;
252 
253  request = FindRequestById(downloadId);
254  if (request != NULL)
255  {
256  VERIFY_MAGIC(request);
257 
258  redirectUrl = httpGetRequestRedirect(request->handle);
259  }
260 
261  return redirectUrl;
262 }
263 
270 {
271  U64BIT numerator;
272  MeasureRequest *request;
273  U32BIT timeDiff, speed;
274 
275  request = FindRequestById(downloadId);
276  if (request != NULL)
277  {
278  /* Report speed in terms of bytes / second */
279  if (ULL_IsValid(request->receivedBytes))
280  {
281  timeDiff = request->finishTime - request->startTime;
282  if (timeDiff == 0)
283  {
284  /* Avoid the division by zero */
285  speed = -1;
286  }
287  else
288  {
289  /* speed = receivedBytes * 1000 / timeDiff */
290  numerator = request->receivedBytes;
291  ULL_Mul32(numerator, 1000);
292  ULL_Div32(numerator, timeDiff);
293  speed = ULL_Get32(numerator);
294  }
295  }
296  else
297  {
298  speed = -1;
299  }
300 
302  }
303 }
304 
311 {
312  MeasureRequest *request;
313 
314  request = FindRequestById(downloadId);
315  if (request != NULL)
316  {
317  VERIFY_MAGIC(request);
318 
319  assert(request->handle != NULL);
320  httpStopRequest(request->handle);
321  }
322 }
323 
330 {
331  MeasureRequest **pRequest, *request;
332 
333  pRequest = &measureRequestList;
334  while (*pRequest != NULL)
335  {
336  request = *pRequest;
337  if (request->downloadId == downloadId)
338  {
339  VERIFY_MAGIC(request);
340 
341  assert(request->handle != NULL);
342  httpDestroyRequest(request->handle);
343  request->handle = NULL;
344 
345  *pRequest = request->next;
346  MHEG5freeMem(request);
347 
348  break;
349  }
350  else
351  {
352  pRequest = &request->next;
353  }
354  }
355 }
356 
357 /*******************
358  * LOCAL FUNCTION *
359  ********************/
360 
361 
367 static MeasureRequest* FindRequestById(U32BIT downloadId)
368 {
369  MeasureRequest *request;
370 
371  request = measureRequestList;
372  while (request != NULL && request->downloadId != downloadId)
373  {
374  request = request->next;
375  }
376 
377  return request;
378 }
379 
387 static BOOLEAN HeaderCallback(void *userdata, U32BIT downloadId,
388  HttpResponse_t *response)
389 {
390  MeasureRequest *request = userdata;
391 
392  VERIFY_MAGIC(request);
393 
394  if (response->data_len <= 2)
395  {
396  /* End of headers */
397  request->code = response->code;
398  }
399 
400  return TRUE;
401 }
402 
410 static BOOLEAN ContentCallback(void *userdata, U32BIT downloadId,
411  HttpResponse_t *response)
412 {
413  MeasureRequest *request = userdata;
414  BOOLEAN more = TRUE;
415 
416  VERIFY_MAGIC(request);
417 
418  if (response->status == HTTP_STATUS_WAIT)
419  {
420  more = HandleMeasureData(request, response->data_len);
421  }
422  else
423  {
424  more = HandleMeasureEnd(request, response);
425  }
426 
427  return more;
428 }
429 
436 static BOOLEAN HandleMeasureData(MeasureRequest *request, U32BIT bytes)
437 {
438  MHEG5eventMessage_t event;
439  E_MhegErr cqu_err;
440  BOOLEAN more = TRUE;
441 
442  if (request->code == 200 || request->code == 206)
443  {
444  /* Update bytes received */
445  ULL_Add32(request->receivedBytes, bytes);
446 
447  if (ULL_Compare(request->receivedBytes,
448  request->maxReceivedBytes) >= 0)
449  {
450  /* Update finish time */
452  more = FALSE;
453  }
454  }
455 
456  if (!more)
457  {
458  /* Update status */
459  request->status = HTTP_STATUS_OK;
460 
461  /* HandleMeasureEnd will not be called, as more=FALSE. So the
462  * event must be sent here.
463  */
464  event.proc_msg_func = (F_MSG_PROCESS)MHEG5StreamerHandle;
465  event.data_type = DT_VALUE;
466  event.data.streamer.requestId = request->downloadId;
467  event.data.streamer.eventType = MHEG5_STREAMER_EVENT_MSP_DOWNLOAD_DONE;
468 
469  cqu_err = VQ_PutMsg(&event, PRTY_NORMAL);
470  if (cqu_err != MHERR_OK)
471  {
472  DBG(("HandleMeasureData: Cannot send MHEG5_STREAMER_EVENT_MSP_DOWNLOAD_DONE event\n"));
473  }
474  }
475 
476  return more;
477 }
478 
485 static BOOLEAN HandleMeasureEnd(MeasureRequest *request,
486  HttpResponse_t *response)
487 {
488  MHEG5eventMessage_t event;
489  E_MhegErr cqu_err;
490 
491  /* Perform the following only if the request hasn't finished yet */
492  if (request->finishTime == 0)
493  {
494  /* Update status */
495  request->status = response->status;
496 
497  /* Update finish time */
499 
500  event.proc_msg_func = (F_MSG_PROCESS)MHEG5StreamerHandle;
501  event.data_type = DT_VALUE;
502  event.data.streamer.requestId = request->downloadId;
503  event.data.streamer.eventType = MHEG5_STREAMER_EVENT_MSP_DOWNLOAD_DONE;
504 
505  cqu_err = VQ_PutMsg(&event, PRTY_NORMAL);
506  if (cqu_err != MHERR_OK)
507  {
508  DBG(("HandleMeasureEnd: Cannot send MHEG5_STREAMER_EVENT_MSP_DOWNLOAD_DONE event %d\n", cqu_err));
509  }
510  }
511  return TRUE;
512 }
513 
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
Basis MHEG5 data types.
E_MhegErr VQ_PutMsg(S_MhegMessage *pMsg, E_PRIORITY priority)
Post event or section message on queue. Copies data into queue.
Definition: glue_queue.c:248
void MHEG5StopMeasureRequest(U32BIT downloadId)
Stop HTTP streaming performance measurement request.
Definition: stmr_msp.c:310
#define ULL_IsValid(variable)
Definition: glue_ulong.h:90
U32BIT downloadId
Definition: stmr_msp.c:72
Utilitiy functions for IC Streamer.
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...
Definition: stmr_util.c:98
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.
E_HttpStatus
Definition: httptype.h:36
Common header internal to IC streamer.
E_HttpStatus status
MHEG5 queue.
U64BIT receivedBytes
Definition: stmr_msp.c:87
struct sMeasureRequest * next
Definition: stmr_msp.c:91
#define MHEG5getMem
Definition: glue_memory.h:93
S32BIT MHEG5GetMeasureStatus(U32BIT downloadId)
Return HTTP status of performance measurement request.
Definition: stmr_msp.c:226
E_MhegErr
Definition: mherrors.h:28
U32BIT startTime
Definition: stmr_msp.c:85
void MHEG5StartMeasureRequest(U32BIT downloadId)
Start HTTP streaming performance measurement request.
Definition: stmr_msp.c:185
void(* F_MSG_PROCESS)(void *data)
Function to Process voyager message.
Definition: glue_queue.h:70
uint8_t U8BIT
Definition: techtype.h:82
U8BIT * MHEG5GetMeasureRedirect(U32BIT downloadId)
Return the redirection URL for a request that was redirected (HTTP status 3xx).
Definition: stmr_msp.c:248
struct sMeasureRequest MeasureRequest
Memory functions.
#define MHEG5freeMem
Definition: glue_memory.h:94
#define SET_MAGIC(r)
Definition: stmr_msp.c:52
HttpRequest_t handle
Definition: stmr_msp.c:78
API for IC streamer.
U8BIT * httpGetRequestRedirect(HttpRequest_t request)
Return the URL that the request is redirected to (valid only for response codes of 3xx)...
This file defines the profile for the MHEG engine.
#define ULL_Mul32(variable, value)
Definition: glue_ulong.h:84
S32BIT MHEG5GetMeasureResponseCode(U32BIT downloadId)
Return response code for performance measurement request.
Definition: stmr_msp.c:205
U32BIT magic
Definition: stmr_msp.c:69
#define VERIFY_MAGIC(r)
Definition: stmr_msp.c:53
void MHEG5DestroyMeasureRequest(U32BIT downloadId)
Destroy HTTP streaming performance measurement request.
Definition: stmr_msp.c:329
void httpStopRequest(HttpRequest_t request)
Stop an HTTP request. This function does not destroy the request; this is done using httpDestroyReque...
int32_t S32BIT
Definition: techtype.h:87
#define DBG(x)
Definition: stmr_msp.c:61
U32BIT MHEG5CreateMeasureRequest(U32BIT requestId, char *url, S32BIT maxBytes)
Create HTTP streaming performance measurement request.
Definition: stmr_msp.c:119
U32BIT finishTime
Definition: stmr_msp.c:86
#define FALSE
Definition: techtype.h:68
#define ULL_Compare(first, second)
Definition: glue_ulong.h:93
void httpDestroyRequest(HttpRequest_t request)
Destroy an HTTP request.
IC Streamer performance measurement.
void MHEG5StreamerHandle(MHEG5StreamerEventParams_t *params)
Process an MHEG5StreamerEvent message The event is passed onto the streamer module for processing...
void MHEG5StreamerNotifyStreamingPerformance(U32BIT requestId, U32BIT speed)
Notify measured streaming performance (speed).
#define ULL_Set32(variable, value)
Definition: glue_ulong.h:88
E_HttpStatus status
Definition: stmr_msp.c:82
U8BIT BOOLEAN
Definition: techtype.h:99
#define ULL_Div32(variable, value)
Definition: glue_ulong.h:85
#define TRUE
Definition: techtype.h:69
U32BIT requestId
Definition: stmr_msp.c:75
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.
#define MHEG5_MAX_RANGE_BUFFER
Definition: stmr_util.h:35
U64BIT maxReceivedBytes
Definition: stmr_msp.c:88
struct HttpRequest_tag * HttpRequest_t
S32BIT code
Definition: stmr_msp.c:81
#define ULL_Get32(variable)
Definition: glue_ulong.h:79
uint32_t U32BIT
Definition: techtype.h:86
void MHEG5ProcessMeasureRequest(U32BIT downloadId)
Process HTTP streaming performance measurement request.
Definition: stmr_msp.c:269
#define ULL_Add32(variable, value)
Definition: glue_ulong.h:81
Header file - Function prototypes for operating system.