49 #define DVB_SUBT_TASK_STACK_SIZE 1024 * 5 50 #define DVB_SUBT_TASK_PRIORITY 9 54 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 55 #ifdef STB_CONTROL_TASK_CHANNEL_DEBUG_REQUIRED 56 #define STB_CONTROL_TASK_PRINT(x) DEBUG_PRINTX_CONDITIONAL(DEBUG_STB_OSD) x 58 #define STB_CONTROL_TASK_PRINT(x) STB_SPDebugWrite x 61 #define STB_CONTROL_TASK_PRINT(x) 68 #define PCS 0x10 // Page Composition Segment 69 #define RCS 0x11 // Region Composition Segment 70 #define CDS 0x12 // CLUT Definition Segment 71 #define ODS 0x13 // Object Data Segment 72 #define DDS 0x14 // Display Definition Segment 77 #define EDS 0x80 // End of Display set Segment - DTG Subtitling: 81 #define END_OF_PES_DATA_FIELD_MARKER 0xff 89 #define SYNC_BYTE 0x0f 95 #define PES_HDR_DATA_LEN_BYTE 0x08 98 #define MAX_PES_SIZE (0xffff + 0x06) 101 #define STB_GetMemory(x) STB_DSGetMemory(x) 102 #define STB_FreeMemory(x) STB_DSFreeMemory(x) 115 U16BIT composition_page_id;
116 U16BIT ancillary_page_id;
122 static BOOLEAN initialised = FALSE;
127 static BOOLEAN force_acquisition = TRUE;
130 static void *dvb_subtitle_queue;
131 static void *dvb_subtitle_ptr;
132 static void *dvb_decoder_sem;
133 static void *dvb_display_sem;
134 static void *set_stream_sem;
136 static U8BIT last_pts[5] = {0xff, 0xff, 0xff, 0xff, 0xff};
137 static U8BIT curr_pts[5] = {0xff, 0xff, 0xff, 0xff, 0xff};
139 static U8BIT *next_pes;
141 static U32BIT pes_collection_callback_handle;
144 static U32BIT malloc_array[2][MAX_ARRAY_INDEX];
145 static U32BIT hi_water_allocations;
146 static S16BIT num_allocations;
147 static U32BIT hi_water_mem_alloc;
148 static U32BIT mem_allocation;
150 static BOOLEAN found;
151 static BOOLEAN done_one_malloc_report;
157 static void DVBSubtitlePesCallback(U32BIT handle, U8BIT data_identifier,
void *buffer_ptr, U32BIT buffer_size);
158 static void DelayIfRequired(
void);
159 static void FlushQueue(
void);
160 static BOOLEAN ParseSegment(U8BIT path, U8BIT *data, U16BIT *processed_bytes, U16BIT pes_length);
161 static void DVBSubtTask(
void *unwanted_p);
180 static void DVBSubtitlePesCallback(U32BIT handle, U8BIT data_identifier,
void *buffer_ptr, U32BIT buffer_size)
185 FUNCTION_START(DVBSubtitlePesCallback);
187 USE_UNWANTED_PARAM(handle);
188 USE_UNWANTED_PARAM(data_identifier);
193 memcpy(buffer, buffer_ptr, buffer_size);
195 success =
STB_OSWriteQueue(dvb_subtitle_queue, (
void *)&buffer,
sizeof(U8BIT *), TIMEOUT_NOW);
198 DBGPRINT(
"DVBSubtitlePesCallback: Failed to add pes buffer to subtitle queue");
203 FUNCTION_FINISH(DVBSubtitlePesCallback);
219 static void DelayIfRequired(
void)
221 static U32BIT timestamp;
225 FUNCTION_START(DelayIfRequired);
235 FUNCTION_FINISH(DelayIfRequired);
250 static void FlushQueue(
void)
253 BOOLEAN read_pes_from_queue;
256 FUNCTION_START(FlushQueue);
259 if (next_pes != NULL)
267 read_pes_from_queue =
STB_OSReadQueue(dvb_subtitle_queue, &pes_ptr,
sizeof(U8BIT *), TIMEOUT_NOW);
268 if (read_pes_from_queue == TRUE)
273 while (read_pes_from_queue);
275 FUNCTION_FINISH(FlushQueue);
292 static BOOLEAN ParseSegment(U8BIT path, U8BIT *data, U16BIT *processed_bytes, U16BIT pes_length)
294 U16BIT segment_length;
297 BOOLEAN parsed_ok = FALSE;
298 BOOLEAN ancillary_pg_present;
301 static BOOLEAN page_okay = FALSE;
302 static BOOLEAN comp_cds_allowed;
303 static BOOLEAN comp_ods_allowed;
305 static BOOLEAN undisplayed_data = FALSE;
308 FUNCTION_START(ParseSegment);
311 segment_type = data[1];
313 page_id = (data[2] << 8) + data[3];
321 if ((subtitle_status.composition_page_id == subtitle_status.ancillary_page_id) ||
322 (subtitle_status.ancillary_page_id == 0))
324 ancillary_pg_present = FALSE;
328 ancillary_pg_present = TRUE;
331 segment_length = (data[4] << 8) + data[5] + 6;
334 if ((*processed_bytes + segment_length) >= pes_length)
336 STB_CONTROL_TASK_PRINT((
"ERR LENGTH wrong! peslen=%d,seglen=%d, prc=%d",
337 pes_length, segment_length, *processed_bytes));
339 segment_length = pes_length - *processed_bytes;
342 else if ((data[segment_length] == SYNC_BYTE) ||
343 (data[segment_length] == END_OF_PES_DATA_FIELD_MARKER))
345 switch (segment_type)
349 if (page_id == subtitle_status.composition_page_id)
351 STB_CONTROL_TASK_PRINT((
"\nDDS"));
357 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 360 STB_CONTROL_TASK_PRINT((
"DDS parse error"));
364 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 367 STB_CONTROL_TASK_PRINT((
"\nDDS - not composing page %d", page_id));
375 STB_CONTROL_TASK_PRINT((
"\nPCS - mode %d - %s",
376 ((data[7] & 0x0c) >> 2),
377 (force_acquisition ?
"FORCE MODE CHANGE" :
"")));
380 if (page_id == subtitle_status.composition_page_id)
383 memcpy((
void *)last_pts, (
void *)curr_pts, (
size_t)5);
388 if (undisplayed_data)
390 undisplayed_data = FALSE;
396 STB_CONTROL_TASK_PRINT((
"PCS composing page %d", page_id));
402 parsed_ok =
STB_DSSegmentPCS(data, pes_length, *processed_bytes, force_acquisition);
407 force_acquisition = TRUE;
408 STB_CONTROL_TASK_PRINT((
"PCS parse error in STB_DSSegmentPCS!!"));
414 force_acquisition = FALSE;
424 undisplayed_data = TRUE;
425 comp_cds_allowed = TRUE;
426 comp_ods_allowed = TRUE;
429 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 432 STB_CONTROL_TASK_PRINT((
"PCS - not composing page %d", page_id));
440 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 443 STB_CONTROL_TASK_PRINT((
"+RCS: page=%d", page_id));
447 STB_CONTROL_TASK_PRINT((
"-rcs: page=%d", page_id));
452 ((page_id == subtitle_status.composition_page_id) ||
453 ((page_id == subtitle_status.ancillary_page_id) && ancillary_pg_present)))
461 STB_CONTROL_TASK_PRINT((
"RCS parse error"));
464 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 467 STB_CONTROL_TASK_PRINT((
"RCS - not composing page %d", page_id));
475 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 476 if (page_okay && comp_cds_allowed)
478 STB_CONTROL_TASK_PRINT((
"+CDS: page=%d", page_id));
482 STB_CONTROL_TASK_PRINT((
"-cds: page=%d", page_id));
487 ((page_id == subtitle_status.composition_page_id) ||
488 (page_id == subtitle_status.ancillary_page_id)))
490 if ((page_id == subtitle_status.ancillary_page_id) && (ancillary_pg_present))
492 comp_cds_allowed = FALSE;
494 if ((page_id == subtitle_status.composition_page_id) && (comp_cds_allowed))
499 STB_CONTROL_TASK_PRINT((
"CDS parse error"));
503 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 506 STB_CONTROL_TASK_PRINT((
"CDS - not composing page %d", page_id));
515 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 516 if (page_okay && comp_ods_allowed)
518 STB_CONTROL_TASK_PRINT((
"+ODS: page=%d", page_id));
522 STB_CONTROL_TASK_PRINT((
"-ods: page=%d", page_id));
527 ((page_id == subtitle_status.composition_page_id) ||
528 (page_id == subtitle_status.ancillary_page_id)))
530 if ((page_id == subtitle_status.ancillary_page_id) && (ancillary_pg_present))
532 comp_ods_allowed = FALSE;
533 comp_cds_allowed = FALSE;
535 if ((page_id == subtitle_status.composition_page_id) && (comp_ods_allowed))
542 STB_CONTROL_TASK_PRINT((
"ODS parse error"));
546 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 549 STB_CONTROL_TASK_PRINT((
"ODS - not composing page %d", page_id));
558 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 561 STB_CONTROL_TASK_PRINT((
"+EDS: page=%d", page_id));
565 STB_CONTROL_TASK_PRINT((
"-eds: page=%d", page_id));
570 ((page_id == subtitle_status.composition_page_id) ||
571 ((page_id == subtitle_status.ancillary_page_id) && ancillary_pg_present)))
580 undisplayed_data = FALSE;
584 STB_CONTROL_TASK_PRINT((
"EDS parse error"));
587 #ifdef STB_CONTROL_TASK_PRINT_REQUIRED 590 STB_CONTROL_TASK_PRINT((
"EDS - not composing page %d", page_id));
599 STB_CONTROL_TASK_PRINT((
"Unknown segment code 0x%02x", segment_type));
606 STB_CONTROL_TASK_PRINT((
"LOST sync with segments; PESlen=%d, prc_posn=%d, seglen=%d, dseg=%x",
607 pes_length, *processed_bytes, segment_length, data[segment_length]));
610 (*processed_bytes) += segment_length;
612 FUNCTION_FINISH(ParseSegment);
629 static void DVBSubtTask(
void *unwanted_p)
634 U16BIT data_id_stream_id;
636 U16BIT processed_bytes;
639 U8BIT pes_hdr_data_len;
642 BOOLEAN data_alignment_indicator;
644 BOOLEAN read_pes_from_queue;
647 FUNCTION_START(DVBSubtTask);
649 USE_UNWANTED_PARAM(unwanted_p);
651 subtitle_status.decode_path = INVALID_RES_ID;
652 subtitle_status.subtitle_pid = 0;
653 subtitle_status.composition_page_id = 0;
654 subtitle_status.ancillary_page_id = 0;
656 subtitle_status.stopped = FALSE;
657 subtitle_status.started = FALSE;
658 subtitle_status.enabled = FALSE;
663 data_id_stream_id = 0;
668 pes_hdr_data_len = 0;
671 data_alignment_indicator = FALSE;
673 read_pes_from_queue = FALSE;
677 read_pes_from_queue =
STB_OSReadQueue(dvb_subtitle_queue, &pes_ptr,
sizeof(U8BIT *), 250);
679 if (subtitle_status.decode_path != INVALID_RES_ID)
686 if (read_pes_from_queue)
689 if ((pes_ptr[0] == 0x00) && (pes_ptr[1] == 0x00) && (pes_ptr[2] == 0x01))
692 if (pes_ptr[3] == 0xbd)
697 pes_length = (pes_ptr[4] << 8) + pes_ptr[5] + 6;
699 data_alignment_indicator = (pes_ptr[6] >> 2) & 0x01;
701 pts_dts_flags = (pes_ptr[7] & 0xc0) >> 6;
702 pts_present = ((pts_dts_flags & 0x2) >> 1);
706 pes_hdr_data_len = pes_ptr[PES_HDR_DATA_LEN_BYTE];
716 memset(curr_pts, 0x00, 5);
717 STB_CONTROL_TASK_PRINT((
"PTS error"));
723 memset(curr_pts, 0x00, 5);
724 STB_CONTROL_TASK_PRINT((
"No PTS"));
728 segment_data = PES_HDR_DATA_LEN_BYTE + pes_hdr_data_len + 1;
729 data = &pes_ptr[segment_data];
731 data_id_stream_id = (data[0] << 8) + data[1];
733 processed_bytes = segment_data + 2;
735 if (subtitle_status.decode_path != INVALID_RES_ID)
739 if (memcmp(last_pts, curr_pts, 5) != MATCH)
747 if ((data_id_stream_id == 0x2000) &&
748 (data_alignment_indicator))
752 while (processed_bytes < pes_length)
758 ParseSegment(subtitle_status.decode_path, data,
759 &processed_bytes, pes_length);
763 case END_OF_PES_DATA_FIELD_MARKER:
772 STB_CONTROL_TASK_PRINT((
"Not a sync byte, PES len=%u, processed %u bytes, value=0x%02x",
773 pes_length, processed_bytes, data[0]));
785 data = &pes_ptr[processed_bytes];
806 FUNCTION_FINISH(DVBSubtTask);
823 void* STB_DSGetMemory(U32BIT bytes)
832 mem_allocation += bytes;
836 for (i = 0; i < MAX_ARRAY_INDEX; i++)
838 if (malloc_array[0][i] == 0)
846 malloc_array[0][i] = temp;
847 malloc_array[1][i] = bytes;
854 if (num_allocations > hi_water_allocations)
856 hi_water_allocations = num_allocations;
859 if (mem_allocation > hi_water_mem_alloc)
861 hi_water_mem_alloc = mem_allocation;
868 hi_water_allocations, hi_water_mem_alloc);
870 if ((done_one_malloc_report) && (num_allocations > 2))
872 done_one_malloc_report = FALSE;
889 void STB_DSFreeMemory(
void *addr)
897 for (i = 0; i < MAX_ARRAY_INDEX; i++)
899 if (malloc_array[0][i] == (U32BIT)addr)
908 mem_allocation -= malloc_array[1][i];
909 malloc_array[0][i] = 0;
910 malloc_array[1][i] = 0;
917 if ((num_allocations == 1) && (!done_one_malloc_report))
920 done_one_malloc_report = TRUE;
922 if (num_allocations < 0)
948 subtitle_status.started = FALSE;
949 subtitle_status.stopped = TRUE;
950 subtitle_status.enabled = FALSE;
952 subtitle_status.decode_path = INVALID_RES_ID;
953 subtitle_status.subtitle_pid = 0;
954 subtitle_status.composition_page_id = 0;
955 subtitle_status.ancillary_page_id = 0;
966 dvb_subtitle_ptr =
STB_OSCreateTask(DVBSubtTask, NULL, DVB_SUBT_TASK_STACK_SIZE,
967 DVB_SUBT_TASK_PRIORITY, (U8BIT *)
"DStask");
969 if ((dvb_subtitle_ptr != NULL) && (dvb_decoder_sem != NULL) &&
970 (dvb_display_sem != NULL) && (set_stream_sem != NULL))
972 STB_CONTROL_TASK_PRINT((
"\nDVB subtitle task, bitmaps rendered directly into region, double buffered"));
998 USE_UNWANTED_PARAM(path);
1002 DBGPRINT(
"STB_SUBEnable(%d): enable=%u", path, enable);
1021 subtitle_status.enabled = enable;
1025 DBGPRINT(
"STB_SUBEnable called before initialisation -- IGNORING ");
1044 void STB_SUBStart(U8BIT path, U16BIT pid, U16BIT composition_id, U16BIT ancillary_id)
1050 DBGPRINT(
"STB_SUBStart(%d): PID %d comp pg %d anc pg %d", path, pid, composition_id, ancillary_id);
1075 DBGPRINT(
">>>>>>>>>>>>>>>>>>STB_SUBStop(%d)", path);
1079 subtitle_status.decode_path = INVALID_RES_ID;
1081 DBGPRINT(
"<<<<<<<<<<<<<<<STB_SUBStop()");
1110 DBGPRINT(
"STB_SUBSetStream(%d): %d %d %d", path, pid, composition_id, ancillary_id);
1114 if (subtitle_status.started == TRUE)
1117 subtitle_status.started = FALSE;
1128 force_acquisition = TRUE;
1135 if ((pid !=
STB_DPGetTextPID(path)) || (pid != subtitle_status.subtitle_pid))
1148 if ((composition_id != subtitle_status.composition_page_id) ||
1149 (ancillary_id != subtitle_status.ancillary_page_id))
1158 subtitle_status.decode_path = path;
1159 subtitle_status.subtitle_pid = pid;
1160 subtitle_status.composition_page_id = composition_id;
1161 subtitle_status.ancillary_page_id = ancillary_id;
1164 subtitle_status.started = TRUE;
1172 DBGPRINT(
"STB_SUBSetStream called before initialisation -- IGNORING");
1193 *started = subtitle_status.started;
1194 *shown = subtitle_status.enabled;
1218 *started = subtitle_status.started;
1219 *pid = subtitle_status.subtitle_pid;
1220 *comp_id = subtitle_status.composition_page_id;
1221 *anc_id = subtitle_status.ancillary_page_id;
1222 *enabled = subtitle_status.enabled;
1242 BOOLEAN read_pes_from_queue;
1254 if (next_pes == NULL)
1256 read_pes_from_queue =
STB_OSReadQueue(dvb_subtitle_queue, &pes_ptr,
sizeof(U8BIT *), 0);
1262 read_pes_from_queue = TRUE;
1265 if (next_pes != NULL)
1279 return(read_pes_from_queue);
void STB_DSHide(void)
Prevents subtitles to display what it has decoded.
void * STB_GetMemory(U32BIT bytes)
Attempts to allocate memory from the heap.
void STB_DSResetPhysicalDisplayRegions(void)
Deletes all regions and clears serice_aquired flag.
BOOLEAN STB_DSInitialiseDVBSubtitlesProcessing(void)
Initilises DVB subtitles, allocates a temporary buffer for use as a scratchpad and zero's the display...
S_DISPLAY_SET * STB_DSGetDetails(void)
Gets a pointer to the display set structure.
void STB_DSDisplay(U8BIT path, S_DISPLAY_SET *subtitle_display_set)
The subtitle display function. Provides timing of display and clean up when necessary.
U32BIT STB_OSGetClockDiff(U32BIT timestamp)
Get Difference between Given Time and Current Time.
Header file - macros and function prototypes for public use.
void * STB_OSCreateSemaphore(void)
Create a Semaphore.
Header file - Function prototypes for OSD control.
void STB_SUBInitialise(void)
Initialises subtitling control.
void STB_OSSemaphoreSignal(void *semaphore)
Signal a Semaphore to Release it by decrementing its counter.
void STB_ChangePesCollectionPID(U8BIT path, U16BIT text_pid)
Changes the PID that the DMX is using to gather data on.
U32BIT STB_RegisterPesCollectionCallback(void(*callback_function)(U32BIT, U8BIT, void *, U32BIT), U8BIT lowest_data_identifier, U8BIT highest_data_identifier)
Used to register a callback function that will receive specific PES data packets. In theory...
BOOLEAN STB_DSSegmentDDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the Display Definition segment in accordance with ETSI document ETS 300 743...
Header file - Function prototypes for DVB subtitles.
void STB_OSSemaphoreWait(void *semaphore)
Wait on Semaphore Indefinity or Until Released.
BOOLEAN STB_DSSegmentODS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the Object Data segment in accordance with ETSI document ETS 300 743.
BOOLEAN STB_DSSegmentPCS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes, BOOLEAN force_acquisition)
Processes the Page Composition segment in accordance with ETSI document ETS 300 743.
BOOLEAN STB_DSSetDisplaySetPts(U8BIT path, U8BIT *pts)
Copies the passed PTS into the display set structure.
BOOLEAN STB_DSSegmentCDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the CLUT Definition segment in accordance with ETSI document ETS 300 743.
void STB_FreeMemory(void *addr)
Releases previously allocated heap memory.
void STB_DSCheckDisplaySetTimeout(S_DISPLAY_SET *subtitle_display_set, BOOLEAN timeout_override)
It checks the timeout of the current display set, and removes if/when necessary.
void STB_DSTerminateDisplayCycle(void)
Sets flag to exit display wait while loop.
BOOLEAN STB_DSSegmentRCS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
Processes the Region Composition segment in accordance with ETSI document ETS 300 743...
void STB_SUBStop(U8BIT path)
Stops subtitling display.
void STB_SPDebugWrite(const char *format,...)
Write debug string to serial/debug port. <CR><LF> characters will be automatically added to the end o...
Debug functions header file.
BOOLEAN STB_DSGetNextPesPts(U8BIT *next_pts)
Get the PTS of the next PES packet, does not process next PES, but places on the next PES pointer...
BOOLEAN STB_DSGetPesPts(U8BIT *data, U8BIT *pts)
Extracts the PTS from the PES packet header.
void STB_SUBStatus(BOOLEAN *started, BOOLEAN *shown)
returns the current status information
BOOLEAN STB_OSDEnable(BOOLEAN enable)
Enable/Disable the OSD.
void STB_SUBSetStream(U8BIT path, U16BIT pid, U16BIT composition_id, U16BIT ancillary_id)
Sets the stream IDs to be decoded.
void STB_DSClearDisplaySetStruct(void)
Clears all information from the display set structure.
BOOLEAN STB_OSWriteQueue(void *queue, void *msg, U16BIT msg_size, U16BIT timeout)
Write a message to the queue.
Header file - Function prototypes for operating system.
System Wide Global Technical Data Type Definitions.
void STB_DSResetPhysicalCompositionRegions(void)
Deletes all regions and clears serice_aquired flag.
void * STB_OSCreateTask(void(*function)(void *), void *param, U32BIT stack, U8BIT priority, U8BIT *name)
Create a New Task to the calling process. Upon success, the created task runs on its own stack...
void * STB_OSCreateQueue(U16BIT msg_size, U16BIT msg_max)
Create Queue of given number of messages and size of message.
void STB_DSShow(void)
Allows subtitles to display what it has decoded.
Header file - Function prototypes for DVB subtitles api.
Header file - Function prototypes for heap memory.
BOOLEAN STB_OSReadQueue(void *queue, void *msg, U16BIT msg_size, U16BIT timeout)
Read a message from a queue.
void STB_UnregisterPesCollectionCallback(U32BIT handle)
Used to un-register a callback function that will receive specific PES data packets.
BOOLEAN STB_DSSegmentEDS(U8BIT *data, U16BIT pes_len, U16BIT processed_bytes)
DTG - Digital Terrestrial Television Requirements for Interoperability Subtitling: 28 August 1998: Ve...
void STB_OSTaskDelay(U16BIT timeout)
Delay Task for Specifed Time Period.
Header file - Function prototypes for Demux control.
Header file - Function prototypes for PES collection task.
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
void STB_SUBReadSettings(BOOLEAN *started, U16BIT *pid, U16BIT *comp_id, U16BIT *anc_id, BOOLEAN *enabled)
returns the current status information
U16BIT STB_DPGetTextPID(U8BIT path)
Reads the teletext PID value from decode path store.
void STB_SUBEnable(U8BIT path, BOOLEAN enable)
Enables or disables subtitling display.
void STB_SUBStart(U8BIT path, U16BIT pid, U16BIT composition_id, U16BIT ancillary_id)
Starts subtitling display.