#include #include #include #include #include #include #include #include #include "libzvbi.h" vbi_decoder* decoder = NULL; vbi_export *exporter = NULL; double currentTime = 0; enum Format_t { FORMAT_TXT, FORMAT_HTML, FORMAT_PNG }; class Statistics { public: unsigned int inputFrames; unsigned int outputCaptions; void Print() { printf("Input Frames: %u\n", inputFrames); printf("Output Captions: %u\n", outputCaptions); } }; Statistics g_statistics; Format_t g_format = FORMAT_TXT; void CaptionCallback(vbi_event* event, void* user_data) { vbi_page page; g_statistics.outputCaptions++; // export to stdout vbi_fetch_cc_page(decoder, &page, event->ev.caption.pgno, TRUE); #if 0 if (13 == g_statistics.outputCaptions) { printf("On 13\n"); for (int row = 0; row < page.rows; row++) { for (int column = 0; column < page.columns; column++) { printf("%c", page.text[row * page.columns + column].unicode); } printf("\n"); } } #endif switch (g_format) { case FORMAT_TXT: case FORMAT_HTML: printf("Caption %u:\n", g_statistics.outputCaptions); vbi_export_stdio(exporter, stdout, &page); break; case FORMAT_PNG: { char filename[64]; snprintf(filename, sizeof(filename), "caption%06d.png", g_statistics.outputCaptions); vbi_export_file(exporter, filename, &page); } break; } vbi_unref_page(&page); } unsigned int hextoiOctet(const char *s) { unsigned int result = 0; for (int i = 0; i < 2 && *s; i++, s++) { if (*s >= '0' && *s <= '9') result = result * 16 + *s - '0'; else if (*s >= 'a' && *s <= 'f') result = result * 16 + *s - 'a' + 10; else if (*s >= 'A' && *s <= 'F') result = result * 16 + *s - 'A' + 10; } return result; } void ProcessFile(const char *filename) { std::ifstream infile(filename); while (infile.good()) { std::string line; vbi_sliced sliced[30]; // Get input infile >> line; if (line.length() != 4) continue; g_statistics.inputFrames++; // Pass to ZVBI memset(sliced, 0, sizeof(sliced)); sliced[0].id = VBI_SLICED_CAPTION_525; sliced[0].line = 21; memset(sliced[0].data, 0, sizeof(sliced[0].data)); sliced[0].data[0] = hextoiOctet(line.c_str()); sliced[0].data[1] = hextoiOctet(line.c_str() + 2); currentTime += 0.03; vbi_decode(decoder, sliced, 1, currentTime); } infile.close(); } int main(int argc, char **argv) { int opt; const char *filename; unsigned short eventMask = VBI_EVENT_CAPTION; //unsigned short eventMask = 0xFFFF; char *errstr; memset(&g_statistics, 0, sizeof(g_statistics)); while ((opt = getopt(argc, argv, "f:")) != -1) { switch(opt){ case 'f': if (strcasecmp(optarg, "txt") == 0 || strcasecmp(optarg, "text") == 0) g_format = FORMAT_TXT; else if (strcasecmp(optarg, "html") == 0) g_format = FORMAT_HTML; else if (strcasecmp(optarg, "png") == 0) g_format = FORMAT_PNG; else { printf("Unknown format given\n"); return 1; } break; default: printf("Unknown option given\n"); return 1; } } if (argc - optind != 1) { printf("Usage: %s [-f {format}] {scc filename}\n", basename(argv[0])); printf("Format can be text, html, or png\n"); return 1; } filename = argv[optind]; decoder = vbi_decoder_new(); if (!vbi_event_handler_add(decoder, eventMask, CaptionCallback, NULL)) printf("Failed to register event handler\n"); else printf("Registered event handler\n"); switch (g_format) { case FORMAT_TXT: exporter = vbi_export_new("text; charset=UTF-8", &errstr); break; case FORMAT_HTML:exporter = vbi_export_new("html", &errstr); break; case FORMAT_PNG: exporter = vbi_export_new("png", &errstr); break; } ProcessFile(filename); vbi_export_delete(exporter); exporter = NULL; vbi_decoder_delete(decoder); decoder = NULL; g_statistics.Print(); return 0; }