コード例 #1
0
ファイル: ccx_decoders_608.c プロジェクト: slifty/ccextractor
void write_char(const unsigned char c, ccx_decoder_608_context *context)
{
	if (context->mode != MODE_TEXT)
	{
		struct eia608_screen *use_buffer = get_writing_buffer(context);
		/* printf ("\rWriting char [%c] at %s:%d:%d\n",c,
		use_buffer == &wb->data608->buffer1?"B1":"B2",
		wb->data608->cursor_row,wb->data608->cursor_column); */
		use_buffer->characters[context->cursor_row][context->cursor_column] = c;
		use_buffer->colors[context->cursor_row][context->cursor_column] = context->current_color;
		use_buffer->fonts[context->cursor_row][context->cursor_column] = context->font;
		use_buffer->row_used[context->cursor_row] = 1;

		if (use_buffer->empty)
		{
			if (MODE_POPON != context->mode)
				context->current_visible_start_ms = get_visible_start();
		}
		use_buffer->empty=0;

		if (context->cursor_column<CCX_DECODER_608_SCREEN_WIDTH - 1)
			context->cursor_column++;
		if (context->ts_start_of_current_line == -1)
			context->ts_start_of_current_line = get_fts();
		context->ts_last_char_received = get_fts();
	}
}
コード例 #2
0
void _dtvcc_window_update_time_show(ccx_dtvcc_window *window, struct ccx_common_timing_ctx *timing)
{
	char buf[128];
	window->time_ms_show = get_visible_start(timing, 3);
	print_mstime2buf(window->time_ms_show, buf);
	ccx_common_logging.debug_ftn(CCX_DMT_708, "[CEA-708] "
			"[W-%d] show time updated to %s\n", window->number, buf);
}
コード例 #3
0
ファイル: ccx_decoders_608.c プロジェクト: slifty/ccextractor
void erase_both_memories(ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
	erase_memory(context, false);
	// For the visible memory, we write the contents to disk
			// The currently *visible* buffer is leaving, so now we know its ending
			// time. Time to actually write it to file.
	if (write_cc_buffer(context, sub))
		context->screenfuls_counter++;
	context->current_visible_start_ms = get_visible_start();
	context->cursor_column = 0;
	context->cursor_row = 0;
	context->current_color = context->settings->default_color;
	context->font = FONT_REGULAR;

	erase_memory(context, true);
}
コード例 #4
0
ファイル: ccx_decoders_608.c プロジェクト: slifty/ccextractor
/* Process GLOBAL CODES */
void handle_command(/*const */ unsigned char c1, const unsigned char c2, ccx_decoder_608_context *context, struct cc_subtitle *sub)
{
	int changes=0;

	// Handle channel change
	context->channel = context->new_channel;
	if (context->channel != context->my_channel)
		return;

	enum command_code command = COM_UNKNOWN;
	if (c1==0x15)
		c1=0x14;
	if ((c1==0x14 || c1==0x1C) && c2==0x2C)
		command = COM_ERASEDISPLAYEDMEMORY;
	if ((c1==0x14 || c1==0x1C) && c2==0x20)
		command = COM_RESUMECAPTIONLOADING;
	if ((c1==0x14 || c1==0x1C) && c2==0x2F)
		command = COM_ENDOFCAPTION;
	if ((c1==0x14 || c1==0x1C) && c2==0x22)
		command = COM_ALARMOFF;
	if ((c1==0x14 || c1==0x1C) && c2==0x23)
		command = COM_ALARMON;
	if ((c1==0x14 || c1==0x1C) && c2==0x24)
		command = COM_DELETETOENDOFROW;
	if ((c1==0x17 || c1==0x1F) && c2==0x21)
		command = COM_TABOFFSET1;
	if ((c1==0x17 || c1==0x1F) && c2==0x22)
		command = COM_TABOFFSET2;
	if ((c1==0x17 || c1==0x1F) && c2==0x23)
		command = COM_TABOFFSET3;
	if ((c1==0x14 || c1==0x1C) && c2==0x25)
		command = COM_ROLLUP2;
	if ((c1==0x14 || c1==0x1C) && c2==0x26)
		command = COM_ROLLUP3;
	if ((c1==0x14 || c1==0x1C) && c2==0x27)
		command = COM_ROLLUP4;
	if ((c1==0x14 || c1==0x1C) && c2==0x29)
		command = COM_RESUMEDIRECTCAPTIONING;
	if ((c1==0x14 || c1==0x1C) && c2==0x2D)
		command = COM_CARRIAGERETURN;
	if ((c1==0x14 || c1==0x1C) && c2==0x2E)
		command = COM_ERASENONDISPLAYEDMEMORY;
	if ((c1==0x14 || c1==0x1C) && c2==0x21)
		command = COM_BACKSPACE;
	if ((c1==0x14 || c1==0x1C) && c2==0x2b)
		command = COM_RESUMETEXTDISPLAY;

	if ((command == COM_ROLLUP2 || command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings->force_rollup == 1)
		command=COM_FAKE_RULLUP1;

	if ((command == COM_ROLLUP3 || command == COM_ROLLUP4) && context->settings->force_rollup == 2)
		command=COM_ROLLUP2;
	else if (command == COM_ROLLUP4 && context->settings->force_rollup == 3)
		command=COM_ROLLUP3;

	ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCommand begin: %02X %02X (%s)\n", c1, c2, command_type[command]);
	ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCurrent mode: %d  Position: %d,%d  VisBuf: %d\n", context->mode,
		context->cursor_row, context->cursor_column, context->visible_buffer);

	switch (command)
	{
		case COM_BACKSPACE:
			if (context->cursor_column>0)
			{
				context->cursor_column--;
				get_writing_buffer(context)->characters[context->cursor_row][context->cursor_column] = ' ';
			}
			break;
		case COM_TABOFFSET1:
			if (context->cursor_column<CCX_DECODER_608_SCREEN_WIDTH - 1)
				context->cursor_column++;
			break;
		case COM_TABOFFSET2:
			context->cursor_column += 2;
			if (context->cursor_column>CCX_DECODER_608_SCREEN_WIDTH - 1)
				context->cursor_column = CCX_DECODER_608_SCREEN_WIDTH - 1;
			break;
		case COM_TABOFFSET3:
			context->cursor_column += 3;
			if (context->cursor_column>CCX_DECODER_608_SCREEN_WIDTH - 1)
				context->cursor_column = CCX_DECODER_608_SCREEN_WIDTH - 1;
			break;
		case COM_RESUMECAPTIONLOADING:
			context->mode = MODE_POPON;
			break;
		case COM_RESUMETEXTDISPLAY:
			context->mode = MODE_TEXT;
			break;
		case COM_FAKE_RULLUP1:
		case COM_ROLLUP2:
		case COM_ROLLUP3:
		case COM_ROLLUP4:
			if (context->mode == MODE_POPON || context->mode == MODE_PAINTON)
			{
				/* CEA-608 C.10 Style Switching (regulatory)
				[...]if pop-up or paint-on captioning is already present in
				either memory it shall be erased[...] */
				if (write_cc_buffer(context, sub))
					context->screenfuls_counter++;
				erase_memory(context, true);
			}
			erase_memory(context, false);

			// If the reception of data for a row is interrupted by data for the alternate
			// data channel or for text mode, the display of caption text will resume from the same
			// cursor position if a roll-up caption command is received and no PAC is given [...]
			if (context->mode != MODE_TEXT && context->have_cursor_position == 0)
			{
				// If no Preamble Address Code  is received, the base row shall default to row 15
				context->cursor_row = 14; // Default if the previous mode wasn't roll up already.
				context->cursor_column = 0;
				context->have_cursor_position = 1;
			}

			switch (command)
			{
				case COM_FAKE_RULLUP1:
					context->mode = MODE_FAKE_ROLLUP_1;
					break;
				case COM_ROLLUP2:
					context->mode = MODE_ROLLUP_2;
					break;
				case COM_ROLLUP3:
					context->mode = MODE_ROLLUP_3;
					break;
				case COM_ROLLUP4:
					context->mode = MODE_ROLLUP_4;
					break;
				default: // Impossible, but remove compiler warnings
					break;
			}
			break;
		case COM_CARRIAGERETURN:
			if (context->mode == MODE_PAINTON) // CR has no effect on painton mode according to zvbis' code
				break;
			if (context->mode == MODE_POPON) // CFS: Not sure about this. Is there a valid reason for CR in popup?
			{
				context->cursor_column = 0;
				if (context->cursor_row<15)
					context->cursor_row++;
				break;
			}
			if (context->output_format == CCX_OF_TRANSCRIPT)
			{
				write_cc_line(context,sub);
			}

			// In transcript mode, CR doesn't write the whole screen, to avoid
			// repeated lines.
			changes = check_roll_up(context);
			if (changes)
			{
				// Only if the roll up would actually cause a line to disappear we write the buffer
				if (context->output_format != CCX_OF_TRANSCRIPT)
				{
					if (write_cc_buffer(context, sub))
						context->screenfuls_counter++;
					if (context->settings->no_rollup)
						erase_memory(context, true); // Make sure the lines we just wrote aren't written again
				}
			}
			roll_up(context); // The roll must be done anyway of course.
			context->ts_start_of_current_line = -1; // Unknown.
			if (changes)
				context->current_visible_start_ms = get_visible_start();
			context->cursor_column = 0;
			break;
		case COM_ERASENONDISPLAYEDMEMORY:
			erase_memory(context, false);
			break;
		case COM_ERASEDISPLAYEDMEMORY:
			// Write it to disk before doing this, and make a note of the new
			// time it became clear.
			if (context->output_format == CCX_OF_TRANSCRIPT &&
				(context->mode == MODE_FAKE_ROLLUP_1 ||
				context->mode == MODE_ROLLUP_2 ||
				context->mode == MODE_ROLLUP_3 ||
				context->mode == MODE_ROLLUP_4))
			{
				// In transcript mode we just write the cursor line. The previous lines
				// should have been written already, so writing everything produces
				// duplicate lines.
				write_cc_line(context, sub);
			}
			else
			{
				if (context->output_format == CCX_OF_TRANSCRIPT)
					context->ts_start_of_current_line = context->current_visible_start_ms;
				if (write_cc_buffer(context, sub))
					context->screenfuls_counter++;
			}
			erase_memory(context, true);
			context->current_visible_start_ms = get_visible_start();
			break;
		case COM_ENDOFCAPTION: // Switch buffers
			// The currently *visible* buffer is leaving, so now we know its ending
			// time. Time to actually write it to file.
			if (write_cc_buffer(context, sub))
				context->screenfuls_counter++;
			context->visible_buffer = (context->visible_buffer == 1) ? 2 : 1;
			context->current_visible_start_ms = get_visible_start();
			context->cursor_column = 0;
			context->cursor_row = 0;
			context->current_color = context->settings->default_color;
			context->font = FONT_REGULAR;
			context->mode = MODE_POPON;
			break;
		case COM_DELETETOENDOFROW:
			delete_to_end_of_row(context);
			break;
		case COM_ALARMOFF:
		case COM_ALARMON:
			// These two are unused according to Robson's, and we wouldn't be able to do anything useful anyway
			break;
		case COM_RESUMEDIRECTCAPTIONING:
			context->mode = MODE_PAINTON;
			//ccx_common_logging.log_ftn ("\nWarning: Received ResumeDirectCaptioning, this mode is almost impossible.\n");
			//ccx_common_logging.log_ftn ("to transcribe to a text file.\n");
			break;
		default:
			ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rNot yet implemented.\n");
			break;
	}
	ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCurrent mode: %d  Position: %d,%d	VisBuf: %d\n", context->mode,
		context->cursor_row, context->cursor_column, context->visible_buffer);
	ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\rCommand end: %02X %02X (%s)\n", c1, c2, command_type[command]);

}
コード例 #5
0
ファイル: ccx_decoders_608.c プロジェクト: slifty/ccextractor
/* If wb is NULL, then only XDS will be processed */
int process608(const unsigned char *data, int length, void *private_data, struct cc_subtitle *sub)
{
	struct ccx_decoder_608_report  *report = NULL;
	ccx_decoder_608_context *context = private_data;
	static int textprinted = 0;
	int i;
	if (context)
	{
		report = &context->report;
		context->bytes_processed_608 += length;
	}
	if (!data)
	{
		return -1;
	}
	for (i=0; i < length; i=i+2)
	{
		unsigned char hi, lo;
		int wrote_to_screen=0;

		hi = data[i] & 0x7F; // Get rid of parity bit
		lo = data[i+1] & 0x7F; // Get rid of parity bit

		if (hi==0 && lo==0) // Just padding
			continue;

		// printf ("\r[%02X:%02X]\n",hi,lo);

		if (hi>=0x10 && hi<=0x1e) {
			int ch = (hi<=0x17)? 1 : 2;
			if (context == NULL || context->my_field == 2) // Originally: current_field from sequencing.c. Seems to be just to change channel, so context->my_field seems good.
				ch+=2;

			if(report)
				report->cc_channels[ch - 1] = 1;
		}

		if (hi >= 0x01 && hi <= 0x0E && (context == NULL || context->my_field == 2)) // XDS can only exist in field 2.
		{
			if (context)
				context->channel = 3;
			if (!in_xds_mode)
			{
				ts_start_of_xds=get_fts();
				in_xds_mode=1;
			}
			if(report)
				report->xds=1;
		}
		if (hi == 0x0F && in_xds_mode && (context == NULL || context->my_field == 2)) // End of XDS block
		{
			in_xds_mode=0;
			do_end_of_xds (sub, lo);
			if (context)
				context->channel = context->new_channel; // Switch from channel 3
			continue;
		}
		if (hi>=0x10 && hi<=0x1F) // Non-character code or special/extended char
			// http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/CC_CODES.HTML
			// http://www.geocities.com/mcpoodle43/SCC_TOOLS/DOCS/CC_CHARS.HTML
		{
			// We were writing characters before, start a new line for
			// diagnostic output from disCommand()
			if (textprinted == 1 )
			{
				ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\n");
				textprinted = 0;
			}
			if (!context || context->my_field == 2)
				in_xds_mode=0; // Back to normal (CEA 608-8.6.2)
			if (!context) // Not XDS and we don't have a writebuffer, nothing else would have an effect
				continue;
			if (context->last_c1 == hi && context->last_c2 == lo)
			{
				// Duplicate dual code, discard. Correct to do it only in
				// non-XDS, XDS codes shall not be repeated.
				ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Skipping command %02X,%02X Duplicate\n", hi, lo);
				// Ignore only the first repetition
				context->last_c1=-1;
				context->last_c2 = -1;
				continue;
			}
			context->last_c1 = hi;
			context->last_c2 = lo;
			wrote_to_screen = disCommand(hi, lo, context, sub);
			if(sub->got_output)
				break;
		}
		else
		{
			if (in_xds_mode && (context == NULL || context->my_field == 2))
			{
				process_xds_bytes (hi,lo);
				continue;
			}
			if (!context) // No XDS code after this point, and user doesn't want captions.
				continue;

			context->last_c1 = -1;
			context->last_c2 = -1;

			if (hi>=0x20) // Standard characters (always in pairs)
			{
				// Only print if the channel is active
				if (context->channel != context->my_channel)
					continue;

				if( textprinted == 0 )
				{
					ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "\n");
					textprinted = 1;
				}

				handle_single(hi, context);
				handle_single(lo, context);
				wrote_to_screen=1;
				context->last_c1 = 0;
				context->last_c2 = 0;
			}

			if (!textprinted && context->channel == context->my_channel)
			{   // Current FTS information after the characters are shown
				ccx_common_logging.debug_ftn(CCX_DMT_DECODER_608, "Current FTS: %s\n", print_mstime(get_fts()));
				//printf("  N:%u", unsigned(fts_now) );
				//printf("  G:%u", unsigned(fts_global) );
				//printf("  F:%d %d %d %d\n",
				//	   current_field, cb_field1, cb_field2, cb_708 );
			}

			if (wrote_to_screen && context->settings->direct_rollup && // If direct_rollup is enabled and
					(context->mode == MODE_FAKE_ROLLUP_1 || // we are in rollup mode, write now.
					 context->mode == MODE_ROLLUP_2 ||
					 context->mode == MODE_ROLLUP_3 ||
					 context->mode == MODE_ROLLUP_4))
			{
				// We don't increase screenfuls_counter here.
				write_cc_buffer(context, sub);
				context->current_visible_start_ms = get_visible_start();
			}
		}
		if (wrote_to_screen && context->cc_to_stdout)
			fflush (stdout);
	} // for
	return i;
}