diff --git a/src/608_spupng.c b/src/608_spupng.c index ba1677f6..9b7c802b 100644 --- a/src/608_spupng.c +++ b/src/608_spupng.c @@ -205,6 +205,7 @@ spupng_write_ccbuffer(struct spupng_t *sp, struct eia608_screen* data, int row; int empty_buf = 1; + char str[256] = ""; for (row = 0; row < 15; row++) { if (data->row_used[row]) @@ -233,19 +234,7 @@ spupng_write_ccbuffer(struct spupng_t *sp, struct eia608_screen* data, sp->pngfile, strerror(errno)); } fclose(sp->fppng); - - fprintf(sp->fpxml, "fpxml, " end=\"%.3f\"", ((double)ms_end) / 1000); - dbg_print(CCX_DMT_608, " end=\"%.3f\"", ((double)ms_end) / 1000); - fprintf(sp->fpxml, " image=\"%s\"", sp->pngfile); - dbg_print(CCX_DMT_608, " image=\"%s\"", sp->pngfile); - fprintf(sp->fpxml, " xoffset=\"%d\"", sp->xOffset); - dbg_print(CCX_DMT_608, " xoffset=\"%d\"", sp->xOffset); - fprintf(sp->fpxml, " yoffset=\"%d\"", sp->yOffset); - dbg_print(CCX_DMT_608, " yoffset=\"%d\"", sp->yOffset); - fprintf(sp->fpxml, ">\n\n"); - dbg_print(CCX_DMT_608, "-->\n"); - - fflush(sp->fpxml); - + + write_spucomment(sp,str); return 1; } int write_cc_buffer_as_spupng(struct eia608_screen *data,struct s_context_cc608 *context) diff --git a/src/constants.h b/src/constants.h index 39133b2d..0b7418ba 100644 --- a/src/constants.h +++ b/src/constants.h @@ -256,4 +256,7 @@ enum cxx_code_type #define CCX_TXT_IN_USE 2 // Positive autodetected, or forced, etc +#define CCX_OF_TYPE_TEXT 1 +#define CCX_OF_TYPE_IMAGE 2 + #endif diff --git a/src/dvb_subtitle_decoder.c b/src/dvb_subtitle_decoder.c index 03de4e52..d3c8710b 100644 --- a/src/dvb_subtitle_decoder.c +++ b/src/dvb_subtitle_decoder.c @@ -32,8 +32,8 @@ #define snprintf(str,size,format,...) _snprintf(str,size-1,format,__VA_ARGS__) #endif - #include "dvb_subtitle_decoder.h" +#include "spupng_encoder.h" #define DEBUG #ifdef DEBUG @@ -48,13 +48,11 @@ #define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14 #define DVBSUB_DISPLAY_SEGMENT 0x80 - #define RL32(x) (*(unsigned int *)(x)) #define RB32(x) (ntohl(*(unsigned int *)(x))) #define RL16(x) (*(unsigned short int*)(x)) #define RB16(x) (ntohs(*(unsigned short int*)(x))) - #define SCALEBITS 10 #define ONE_HALF (1 << (SCALEBITS - 1)) #define FIX(x) ((int) ((x) * (1<= INT_MAX - 7 || bit_size < 0 || !buffer) { - buffer_size = bit_size = 0; - buffer = NULL; - ret = -1; - errno = EINVAL; - } + if (bit_size >= INT_MAX - 7 || bit_size < 0 || !buffer) + { + buffer_size = bit_size = 0; + buffer = NULL; + ret = -1; + errno = EINVAL; + } - buffer_size = (bit_size + 7) >> 3; + buffer_size = (bit_size + 7) >> 3; - s->buffer = buffer; - s->size_in_bits = bit_size; - s->size_in_bits_plus8 = bit_size + 8; - s->buffer_end = buffer + buffer_size; - s->index = 0; + s->buffer = buffer; + s->size_in_bits = bit_size; + s->size_in_bits_plus8 = bit_size + 8; + s->buffer_end = buffer + buffer_size; + s->index = 0; - return ret; + return ret; } static __inline int get_bits_count(const GetBitContext *s) { - return s->index; + return s->index; } static __inline unsigned int get_bits(GetBitContext *s, int n) { - register int tmp; - unsigned int re_index = s->index; - unsigned int re_cache = 0; - unsigned int re_size_plus8 = s->size_in_bits_plus8; + register int tmp; + unsigned int re_index = s->index; + unsigned int re_cache = 0; + unsigned int re_size_plus8 = s->size_in_bits_plus8; - if(n <=0 && n>25) - return -1; - re_cache = RB32( s->buffer + (re_index >> 3 )) << (re_index & 7); + if (n <= 0 && n > 25) + return -1; + re_cache = RB32( s->buffer + (re_index >> 3 )) << (re_index & 7); - tmp = ((uint32_t) re_cache) >> (32 -n); + tmp = ((uint32_t) re_cache) >> (32 - n); - re_index = ( (re_size_plus8 < re_index + (n) )? ( re_size_plus8 ) : ( re_index + (n)) ); + re_index = ( + (re_size_plus8 < re_index + (n)) ? + (re_size_plus8) : (re_index + (n))); - s->index = re_index; - return tmp; + s->index = re_index; + return tmp; } static __inline unsigned int get_bits1(GetBitContext *s) { - unsigned int index = s->index; - uint8_t result = s->buffer[index >> 3]; + unsigned int index = s->index; + uint8_t result = s->buffer[index >> 3]; - result <<= index & 7; - result >>= 8 - 1; + result <<= index & 7; + result >>= 8 - 1; - if (s->index < s->size_in_bits_plus8) - index++; - s->index = index; + if (s->index < s->size_in_bits_plus8) + index++; + s->index = index; - return result; + return result; } static void freep(void *arg) { - void **ptr = (void **)arg; - free(*ptr); - *ptr = NULL; + void **ptr = (void **) arg; + if (*ptr) + free(*ptr); + *ptr = NULL; } #ifdef DEBUG -static void png_save(const char *filename, uint32_t *bitmap, int w, int h) +static int png_save1(const char *filename, uint8_t *bitmap, int w, int h,uint32_t *clut) { - FILE *f; - char fname[40]; - png_structp png_ptr; - png_infop info_ptr; - png_bytep* row_pointer; + FILE *f = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_bytep* row_pointer = NULL; + int i, j, ret; + int k = 0; static png_color palette[10] = { { 0xff, 0xff, 0xff }, // COL_WHITE = 0, @@ -229,291 +229,418 @@ static void png_save(const char *filename, uint32_t *bitmap, int w, int h) { 0x00, 0x00, 0x00 }, // COL_BLACK = 8 { 0x00, 0x00, 0x00 } // COL_TRANSPARENT = 9 }; + static png_byte alpha[10] = - {255,255,255,255,255,255,255,255,255,0}; - int i =0; - int j =0; - int k =0; - unsigned char array[1024] = ""; + { + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 0 + }; + f = fopen(filename, "wb"); + if (!f) + { + mprint("DVB:unable to open %s in write mode \n", filename); + ret = -1; + goto end; + } - snprintf(fname, sizeof(fname), "%s.png", filename); - f = fopen(fname, "wb"); + if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, + NULL ))) + { + mprint("DVB:unable to create png write struct\n"); + goto end; + } + if (!(info_ptr = png_create_info_struct(png_ptr))) + { + mprint("DVB:unable to create png info struct\n"); + ret = -1; + goto end; + } + + row_pointer = (png_bytep*) malloc(sizeof(png_bytep) * h); + if (!row_pointer) + { + mprint("DVB: unable to allocate row_pointer\n"); + ret = -1; + goto end; + } + memset(row_pointer, 0, sizeof(png_bytep) * h); + png_init_io(png_ptr, f); + + png_set_IHDR (png_ptr, + info_ptr, + w, + h, + /* bit_depth */ 8, + PNG_COLOR_TYPE_PALETTE, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_set_PLTE (png_ptr, info_ptr, palette, sizeof(palette) / sizeof(palette[0])); + png_set_tRNS (png_ptr, info_ptr, alpha, sizeof(alpha) / sizeof(alpha[0]), NULL); + + for (i = 0; i < h; i++) + { + row_pointer[i] = (png_byte*) malloc( + png_get_rowbytes(png_ptr, info_ptr)); + if (row_pointer[i] == NULL ) + break; + } + if (i != h) + { + mprint("DVB: unable to allocate row_pointer internals\n"); + ret = -1; + goto end; + } + + png_write_info(png_ptr, info_ptr); + + for (i = 0; i < h; i++) + { + for (j = 0; j < png_get_rowbytes(png_ptr, info_ptr); j ++) + { + k = bitmap[i * w + (j)]; + row_pointer[i][j] = k;//((k >> 16) & 0xff); + } + } + + png_write_image(png_ptr, row_pointer); + + png_write_end(png_ptr, info_ptr); + end:if (row_pointer) + { + for (i = 0; i < h; i++) + freep(&row_pointer[i]); + freep(&row_pointer); + } + png_destroy_write_struct(&png_ptr, &info_ptr); + if (f) + fclose(f); + return ret; + +} +static int png_save(const char *filename, uint32_t *bitmap, int w, int h) +{ + FILE *f = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_bytep* row_pointer = NULL; + int i, j, ret; + int k = 0; + f = fopen(filename, "wb"); if (!f) { - perror(fname); - return; + mprint("DVB:unable to open %s in write mode \n", filename); + ret = -1; + goto end; } - if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL))) + if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, + NULL ))) { - printf("unable to create png write struct\n"); + mprint("DVB:unable to create png write struct\n"); + goto end; } - if (!(info_ptr = png_create_info_struct(png_ptr))) { - printf("unable to create png info struct\n"); - png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + mprint("DVB:unable to create png info struct\n"); + ret = -1; + goto end; } - row_pointer = (png_bytep*)malloc(sizeof(png_bytep) * h); - if(!row_pointer) + row_pointer = (png_bytep*) malloc(sizeof(png_bytep) * h); + if (!row_pointer) { - printf("unable to allocate row_pointer\n"); - png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + mprint("DVB: unable to allocate row_pointer\n"); + ret = -1; + goto end; } + memset(row_pointer, 0, sizeof(png_bytep) * h); + png_init_io(png_ptr, f); - png_init_io(png_ptr,f); - - png_set_IHDR (png_ptr,info_ptr,w,h, - /* bit_depth */ 8,PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - for (i = 0; i < h; i++) - row_pointer[i] = (png_byte*)malloc(png_get_rowbytes(png_ptr,info_ptr)); - - png_set_tRNS (png_ptr, info_ptr, alpha, sizeof(alpha) / sizeof(alpha[0]), NULL); - png_write_info (png_ptr, info_ptr); + png_set_IHDR(png_ptr, info_ptr, w, h, + /* bit_depth */8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for (i = 0; i < h; i++) { - for(j = 0 ; j < png_get_rowbytes(png_ptr,info_ptr) ; j+=4) + row_pointer[i] = (png_byte*) malloc( + png_get_rowbytes(png_ptr, info_ptr)); + if (row_pointer[i] == NULL ) + break; + } + if (i != h) + { + mprint("DVB: unable to allocate row_pointer internals\n"); + ret = -1; + goto end; + } + + png_write_info(png_ptr, info_ptr); + + for (i = 0; i < h; i++) + { + for (j = 0; j < png_get_rowbytes(png_ptr, info_ptr); j += 4) { - k = bitmap[i * w + (j/4)]; + k = bitmap[i * w + (j / 4)]; row_pointer[i][j] = ((k >> 16) & 0xff); - row_pointer[i][j+1] = ((k >> 8) & 0xff); - row_pointer[i][j+2] = ((k) & 0xff); - row_pointer[i][j+3] = (k >> 24) & 0xff; + row_pointer[i][j + 1] = ((k >> 8) & 0xff); + row_pointer[i][j + 2] = ((k) & 0xff); + row_pointer[i][j + 3] = (k >> 24) & 0xff; } } - png_write_image (png_ptr, row_pointer); + png_write_image(png_ptr, row_pointer); - png_write_end (png_ptr, info_ptr); - - for (i = 0; i < h; i++) - free(row_pointer[i]); - free(row_pointer); - png_destroy_write_struct(&png_ptr, (png_infopp) NULL); - fclose(f); + png_write_end(png_ptr, info_ptr); + end: if (row_pointer) + { + for (i = 0; i < h; i++) + freep(&row_pointer[i]); + freep(&row_pointer); + } + png_destroy_write_struct(&png_ptr, &info_ptr); + if (f) + fclose(f); + return ret; } #endif #define RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) -typedef struct DVBSubCLUT { - int id; - int version; +typedef struct DVBSubCLUT +{ + int id; + int version; - uint32_t clut4[4]; - uint32_t clut16[16]; - uint32_t clut256[256]; + uint32_t clut4[4]; + uint32_t clut16[16]; + uint32_t clut256[256]; - struct DVBSubCLUT *next; + struct DVBSubCLUT *next; } DVBSubCLUT; static DVBSubCLUT default_clut; -typedef struct DVBSubObjectDisplay { - int object_id; - int region_id; +typedef struct DVBSubObjectDisplay +{ + int object_id; + int region_id; - int x_pos; - int y_pos; + int x_pos; + int y_pos; - int fgcolor; - int bgcolor; + int fgcolor; + int bgcolor; - struct DVBSubObjectDisplay *region_list_next; - struct DVBSubObjectDisplay *object_list_next; + struct DVBSubObjectDisplay *region_list_next; + struct DVBSubObjectDisplay *object_list_next; } DVBSubObjectDisplay; -typedef struct DVBSubObject { - int id; - int version; +typedef struct DVBSubObject +{ + int id; + int version; - int type; + int type; - DVBSubObjectDisplay *display_list; + DVBSubObjectDisplay *display_list; - struct DVBSubObject *next; + struct DVBSubObject *next; } DVBSubObject; -typedef struct DVBSubRegionDisplay { - int region_id; +typedef struct DVBSubRegionDisplay +{ + int region_id; - int x_pos; - int y_pos; + int x_pos; + int y_pos; - struct DVBSubRegionDisplay *next; + struct DVBSubRegionDisplay *next; } DVBSubRegionDisplay; -typedef struct DVBSubRegion { - int id; - int version; +typedef struct DVBSubRegion +{ + int id; + int version; - int width; - int height; - int depth; + int width; + int height; + int depth; - int clut; - int bgcolor; + int clut; + int bgcolor; - uint8_t *pbuf; - int buf_size; - int dirty; + uint8_t *pbuf; + int buf_size; + int dirty; - DVBSubObjectDisplay *display_list; + DVBSubObjectDisplay *display_list; - struct DVBSubRegion *next; + struct DVBSubRegion *next; } DVBSubRegion; -typedef struct DVBSubDisplayDefinition { - int version; +typedef struct DVBSubDisplayDefinition +{ + int version; - int x; - int y; - int width; - int height; + int x; + int y; + int width; + int height; } DVBSubDisplayDefinition; -typedef struct DVBSubContext { - int composition_id; - int ancillary_id; +typedef struct DVBSubContext +{ + int composition_id; + int ancillary_id; - int version; - int time_out; - DVBSubRegion *region_list; - DVBSubCLUT *clut_list; - DVBSubObject *object_list; + int version; + int time_out; + DVBSubRegion *region_list; + DVBSubCLUT *clut_list; + DVBSubObject *object_list; - DVBSubRegionDisplay *display_list; - DVBSubDisplayDefinition *display_definition; + DVBSubRegionDisplay *display_list; + DVBSubDisplayDefinition *display_definition; + struct ccx_s_write *out; } DVBSubContext; - static DVBSubObject* get_object(DVBSubContext *ctx, int object_id) { - DVBSubObject *ptr = ctx->object_list; + DVBSubObject *ptr = ctx->object_list; - while (ptr && ptr->id != object_id) { - ptr = ptr->next; - } + while (ptr && ptr->id != object_id) + ptr = ptr->next; - return ptr; + return ptr; } static DVBSubCLUT* get_clut(DVBSubContext *ctx, int clut_id) { - DVBSubCLUT *ptr = ctx->clut_list; + DVBSubCLUT *ptr = ctx->clut_list; - while (ptr && ptr->id != clut_id) { - ptr = ptr->next; - } + while (ptr && ptr->id != clut_id) + ptr = ptr->next; - return ptr; + return ptr; } static DVBSubRegion* get_region(DVBSubContext *ctx, int region_id) { - DVBSubRegion *ptr = ctx->region_list; + DVBSubRegion *ptr = ctx->region_list; - while (ptr && ptr->id != region_id) { - ptr = ptr->next; - } + while (ptr && ptr->id != region_id) + ptr = ptr->next; - return ptr; + return ptr; } static void delete_region_display_list(DVBSubContext *ctx, DVBSubRegion *region) { - DVBSubObject *object, *obj2, **obj2_ptr; - DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr; + DVBSubObject *object, *obj2, **obj2_ptr; + DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr; - while (region->display_list) { - display = region->display_list; + while (region->display_list) + { + display = region->display_list; - object = get_object(ctx, display->object_id); + object = get_object(ctx, display->object_id); - if (object) { - obj_disp_ptr = &object->display_list; - obj_disp = *obj_disp_ptr; + if (object) + { + obj_disp_ptr = &object->display_list; + obj_disp = *obj_disp_ptr; - while (obj_disp && obj_disp != display) { - obj_disp_ptr = &obj_disp->object_list_next; - obj_disp = *obj_disp_ptr; - } + while (obj_disp && obj_disp != display) + { + obj_disp_ptr = &obj_disp->object_list_next; + obj_disp = *obj_disp_ptr; + } - if (obj_disp) { - *obj_disp_ptr = obj_disp->object_list_next; + if (obj_disp) + { + *obj_disp_ptr = obj_disp->object_list_next; - if (!object->display_list) { - obj2_ptr = &ctx->object_list; - obj2 = *obj2_ptr; + if (!object->display_list) + { + obj2_ptr = &ctx->object_list; + obj2 = *obj2_ptr; - while (obj2 != object) { - assert(obj2); - obj2_ptr = &obj2->next; - obj2 = *obj2_ptr; - } + while (obj2 != object) + { + assert(obj2); + obj2_ptr = &obj2->next; + obj2 = *obj2_ptr; + } - *obj2_ptr = obj2->next; + *obj2_ptr = obj2->next; - free(obj2); - } - } - } + free(obj2); + } + } + } - region->display_list = display->region_list_next; + region->display_list = display->region_list_next; - free(display); - } + free(display); + } } static void delete_cluts(DVBSubContext *ctx) { - DVBSubCLUT *clut; + DVBSubCLUT *clut; - while (ctx->clut_list) { - clut = ctx->clut_list; + while (ctx->clut_list) + { + clut = ctx->clut_list; - ctx->clut_list = clut->next; + ctx->clut_list = clut->next; - free(clut); - } + free(clut); + } } static void delete_objects(DVBSubContext *ctx) { - DVBSubObject *object; + DVBSubObject *object; - while (ctx->object_list) { - object = ctx->object_list; + while (ctx->object_list) + { + object = ctx->object_list; - ctx->object_list = object->next; + ctx->object_list = object->next; - free(object); - } + free(object); + } } static void delete_regions(DVBSubContext *ctx) { - DVBSubRegion *region; + DVBSubRegion *region; - while (ctx->region_list) { - region = ctx->region_list; + while (ctx->region_list) + { + region = ctx->region_list; - ctx->region_list = region->next; + ctx->region_list = region->next; - delete_region_display_list(ctx, region); + delete_region_display_list(ctx, region); - free(region->pbuf); - free(region); - } + free(region->pbuf); + free(region); + } } /** * @param composition_id composition-page_id found in Subtitle descriptors @@ -526,1114 +653,1230 @@ static void delete_regions(DVBSubContext *ctx) * @return DVB context kept as void* for abstraction * */ -void* dvbsub_init_decoder(int composition_id,int ancillary_id) +void* dvbsub_init_decoder(int composition_id, int ancillary_id) { - int i, r, g, b, a = 0; - DVBSubContext *ctx = (DVBSubContext*)malloc(sizeof(DVBSubContext)); - memset(ctx,0,sizeof(DVBSubContext)); + int i, r, g, b, a = 0; + DVBSubContext *ctx = (DVBSubContext*) malloc(sizeof(DVBSubContext)); + memset(ctx, 0, sizeof(DVBSubContext)); - ctx->composition_id = composition_id; - ctx->ancillary_id = ancillary_id; + ctx->composition_id = composition_id; + ctx->ancillary_id = ancillary_id; - ctx->version = -1; + ctx->version = -1; - default_clut.id = -1; - default_clut.next = NULL; + default_clut.id = -1; + default_clut.next = NULL; - default_clut.clut4[0] = RGBA( 0, 0, 0, 0); - default_clut.clut4[1] = RGBA(255, 255, 255, 255); - default_clut.clut4[2] = RGBA( 0, 0, 0, 255); - default_clut.clut4[3] = RGBA(127, 127, 127, 255); + default_clut.clut4[0] = RGBA( 0, 0, 0, 0); + default_clut.clut4[1] = RGBA(255, 255, 255, 255); + default_clut.clut4[2] = RGBA( 0, 0, 0, 255); + default_clut.clut4[3] = RGBA(127, 127, 127, 255); - default_clut.clut16[0] = RGBA( 0, 0, 0, 0); - for (i = 1; i < 16; i++) { - if (i < 8) { - r = (i & 1) ? 255 : 0; - g = (i & 2) ? 255 : 0; - b = (i & 4) ? 255 : 0; - } else { - r = (i & 1) ? 127 : 0; - g = (i & 2) ? 127 : 0; - b = (i & 4) ? 127 : 0; - } - default_clut.clut16[i] = RGBA(r, g, b, 255); - } + default_clut.clut16[0] = RGBA( 0, 0, 0, 0); + for (i = 1; i < 16; i++) + { + if (i < 8) + { + r = (i & 1) ? 255 : 0; + g = (i & 2) ? 255 : 0; + b = (i & 4) ? 255 : 0; + } + else + { + r = (i & 1) ? 127 : 0; + g = (i & 2) ? 127 : 0; + b = (i & 4) ? 127 : 0; + } + default_clut.clut16[i] = RGBA(r, g, b, 255); + } - default_clut.clut256[0] = RGBA( 0, 0, 0, 0); - for (i = 1; i < 256; i++) { - if (i < 8) { - r = (i & 1) ? 255 : 0; - g = (i & 2) ? 255 : 0; - b = (i & 4) ? 255 : 0; - a = 63; - } else { - switch (i & 0x88) { - case 0x00: - r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); - g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); - b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); - a = 255; - break; - case 0x08: - r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); - g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); - b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); - a = 127; - break; - case 0x80: - r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); - g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); - b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); - a = 255; - break; - case 0x88: - r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); - g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); - b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); - a = 255; - break; - } - } - default_clut.clut256[i] = RGBA(r, g, b, a); - } + default_clut.clut256[0] = RGBA( 0, 0, 0, 0); + for (i = 1; i < 256; i++) + { + if (i < 8) + { + r = (i & 1) ? 255 : 0; + g = (i & 2) ? 255 : 0; + b = (i & 4) ? 255 : 0; + a = 63; + } + else + { + switch (i & 0x88) + { + case 0x00: + r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); + g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); + b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); + a = 255; + break; + case 0x08: + r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); + g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); + b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); + a = 127; + break; + case 0x80: + r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); + g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); + b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); + a = 255; + break; + case 0x88: + r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); + g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); + b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); + a = 255; + break; + } + } + default_clut.clut256[i] = RGBA(r, g, b, a); + } - return (void*)ctx; + return (void*) ctx; } int dvbsub_close_decoder(void *dvb_ctx) { - DVBSubContext *ctx = (DVBSubContext *)dvb_ctx; - DVBSubRegionDisplay *display; + DVBSubContext *ctx = (DVBSubContext *) dvb_ctx; + DVBSubRegionDisplay *display; - delete_regions(ctx); + delete_regions(ctx); - delete_objects(ctx); + delete_objects(ctx); - delete_cluts(ctx); + delete_cluts(ctx); - freep(&ctx->display_definition); + freep(&ctx->display_definition); - while (ctx->display_list) { - display = ctx->display_list; - ctx->display_list = display->next; - free(display); - } + while (ctx->display_list) + { + display = ctx->display_list; + ctx->display_list = display->next; + free(display); + } - return 0; + return 0; } static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len, - const uint8_t **srcbuf, int buf_size, - int non_mod, uint8_t *map_table, int x_pos) + const uint8_t **srcbuf, int buf_size, int non_mod, uint8_t *map_table, + int x_pos) { - GetBitContext gb; + GetBitContext gb; - int bits; - int run_length; - int pixels_read = x_pos; + int bits; + int run_length; + int pixels_read = x_pos; - init_get_bits(&gb, *srcbuf, buf_size << 3); + init_get_bits(&gb, *srcbuf, buf_size << 3); - destbuf += x_pos; + destbuf += x_pos; - while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) { - bits = get_bits(&gb, 2); + while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) + { + bits = get_bits(&gb, 2); - if (bits) { - if (non_mod != 1 || bits != 1) { - if (map_table) - *destbuf++ = map_table[bits]; - else - *destbuf++ = bits; - } - pixels_read++; - } else { - bits = get_bits1(&gb); - if (bits == 1) { - run_length = get_bits(&gb, 3) + 3; - bits = get_bits(&gb, 2); + if (bits) + { + if (non_mod != 1 || bits != 1) + { + if (map_table) + *destbuf++ = map_table[bits]; + else + *destbuf++ = bits; + } + pixels_read++; + } + else + { + bits = get_bits1(&gb); + if (bits == 1) + { + run_length = get_bits(&gb, 3) + 3; + bits = get_bits(&gb, 2); - if (non_mod == 1 && bits == 1) - pixels_read += run_length; - else { - if (map_table) - bits = map_table[bits]; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } - } else { - bits = get_bits1(&gb); - if (bits == 0) { - bits = get_bits(&gb, 2); - if (bits == 2) { - run_length = get_bits(&gb, 4) + 12; - bits = get_bits(&gb, 2); + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else + { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + } + else + { + bits = get_bits1(&gb); + if (bits == 0) + { + bits = get_bits(&gb, 2); + if (bits == 2) + { + run_length = get_bits(&gb, 4) + 12; + bits = get_bits(&gb, 2); - if (non_mod == 1 && bits == 1) - pixels_read += run_length; - else { - if (map_table) - bits = map_table[bits]; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } - } else if (bits == 3) { - run_length = get_bits(&gb, 8) + 29; - bits = get_bits(&gb, 2); + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else + { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + } + else if (bits == 3) + { + run_length = get_bits(&gb, 8) + 29; + bits = get_bits(&gb, 2); - if (non_mod == 1 && bits == 1) - pixels_read += run_length; - else { - if (map_table) - bits = map_table[bits]; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } - } else if (bits == 1) { - if (map_table) - bits = map_table[0]; - else - bits = 0; - run_length = 2; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } else { - (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; - return pixels_read; - } - } else { - if (map_table) - bits = map_table[0]; - else - bits = 0; - *destbuf++ = bits; - pixels_read++; - } - } - } - } + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else + { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + } + else if (bits == 1) + { + if (map_table) + bits = map_table[0]; + else + bits = 0; + run_length = 2; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + else + { + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + return pixels_read; + } + } + else + { + if (map_table) + bits = map_table[0]; + else + bits = 0; + *destbuf++ = bits; + pixels_read++; + } + } + } + } - if (get_bits(&gb, 6)) - printf("DVBSub error: line overflow\n"); + if (get_bits(&gb, 6)) + mprint("DVBSub error: line overflow\n"); - (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; - return pixels_read; + return pixels_read; } static int dvbsub_read_4bit_string(uint8_t *destbuf, int dbuf_len, - const uint8_t **srcbuf, int buf_size, - int non_mod, uint8_t *map_table, int x_pos) + const uint8_t **srcbuf, int buf_size, int non_mod, uint8_t *map_table, + int x_pos) { - GetBitContext gb; + GetBitContext gb; - int bits; - int run_length; - int pixels_read = x_pos; + int bits; + int run_length; + int pixels_read = x_pos; - init_get_bits(&gb, *srcbuf, buf_size << 3); + init_get_bits(&gb, *srcbuf, buf_size << 3); - destbuf += x_pos; + destbuf += x_pos; - while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) { - bits = get_bits(&gb, 4); + while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) + { + bits = get_bits(&gb, 4); - if (bits) { - if (non_mod != 1 || bits != 1) { - if (map_table) - *destbuf++ = map_table[bits]; - else - *destbuf++ = bits; - } - pixels_read++; - } else { - bits = get_bits1(&gb); - if (bits == 0) { - run_length = get_bits(&gb, 3); + if (bits) + { + if (non_mod != 1 || bits != 1) + { + if (map_table) + *destbuf++ = map_table[bits]; + else + *destbuf++ = bits; + } + pixels_read++; + } + else + { + bits = get_bits1(&gb); + if (bits == 0) + { + run_length = get_bits(&gb, 3); - if (run_length == 0) { - (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; - return pixels_read; - } + if (run_length == 0) + { + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + return pixels_read; + } - run_length += 2; + run_length += 2; - if (map_table) - bits = map_table[0]; - else - bits = 0; + if (map_table) + bits = map_table[0]; + else + bits = 0; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } else { - bits = get_bits1(&gb); - if (bits == 0) { - run_length = get_bits(&gb, 2) + 4; - bits = get_bits(&gb, 4); + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + else + { + bits = get_bits1(&gb); + if (bits == 0) + { + run_length = get_bits(&gb, 2) + 4; + bits = get_bits(&gb, 4); - if (non_mod == 1 && bits == 1) - pixels_read += run_length; - else { - if (map_table) - bits = map_table[bits]; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } - } else { - bits = get_bits(&gb, 2); - if (bits == 2) { - run_length = get_bits(&gb, 4) + 9; - bits = get_bits(&gb, 4); + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else + { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + } + else + { + bits = get_bits(&gb, 2); + if (bits == 2) + { + run_length = get_bits(&gb, 4) + 9; + bits = get_bits(&gb, 4); - if (non_mod == 1 && bits == 1) - pixels_read += run_length; - else { - if (map_table) - bits = map_table[bits]; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } - } else if (bits == 3) { - run_length = get_bits(&gb, 8) + 25; - bits = get_bits(&gb, 4); + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else + { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + } + else if (bits == 3) + { + run_length = get_bits(&gb, 8) + 25; + bits = get_bits(&gb, 4); - if (non_mod == 1 && bits == 1) - pixels_read += run_length; - else { - if (map_table) - bits = map_table[bits]; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } - } else if (bits == 1) { - if (map_table) - bits = map_table[0]; - else - bits = 0; - run_length = 2; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } else { - if (map_table) - bits = map_table[0]; - else - bits = 0; - *destbuf++ = bits; - pixels_read ++; - } - } - } - } - } + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else + { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + } + else if (bits == 1) + { + if (map_table) + bits = map_table[0]; + else + bits = 0; + run_length = 2; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + else + { + if (map_table) + bits = map_table[0]; + else + bits = 0; + *destbuf++ = bits; + pixels_read++; + } + } + } + } + } - if (get_bits(&gb, 8)) - printf("DVBSub error: line overflow\n"); + if (get_bits(&gb, 8)) + mprint("DVBSub error: line overflow\n"); - (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; - return pixels_read; + return pixels_read; } static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len, - const uint8_t **srcbuf, int buf_size, - int non_mod, uint8_t *map_table, int x_pos) + const uint8_t **srcbuf, int buf_size, int non_mod, uint8_t *map_table, + int x_pos) { - const uint8_t *sbuf_end = (*srcbuf) + buf_size; - int bits; - int run_length; - int pixels_read = x_pos; + const uint8_t *sbuf_end = (*srcbuf) + buf_size; + int bits; + int run_length; + int pixels_read = x_pos; - destbuf += x_pos; + destbuf += x_pos; - while (*srcbuf < sbuf_end && pixels_read < dbuf_len) { - bits = *(*srcbuf)++; + while (*srcbuf < sbuf_end && pixels_read < dbuf_len) + { + bits = *(*srcbuf)++; - if (bits) { - if (non_mod != 1 || bits != 1) { - if (map_table) - *destbuf++ = map_table[bits]; - else - *destbuf++ = bits; - } - pixels_read++; - } else { - bits = *(*srcbuf)++; - run_length = bits & 0x7f; - if ((bits & 0x80) == 0) { - if (run_length == 0) { - return pixels_read; - } + if (bits) + { + if (non_mod != 1 || bits != 1) + { + if (map_table) + *destbuf++ = map_table[bits]; + else + *destbuf++ = bits; + } + pixels_read++; + } + else + { + bits = *(*srcbuf)++; + run_length = bits & 0x7f; + if ((bits & 0x80) == 0) + { + if (run_length == 0) + { + return pixels_read; + } - if (map_table) - bits = map_table[0]; - else - bits = 0; - while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } else { - bits = *(*srcbuf)++; + if (map_table) + bits = map_table[0]; + else + bits = 0; + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + else + { + bits = *(*srcbuf)++; - if (non_mod == 1 && bits == 1) - pixels_read += run_length; - if (map_table) - bits = map_table[bits]; - else while (run_length-- > 0 && pixels_read < dbuf_len) { - *destbuf++ = bits; - pixels_read++; - } - } - } - } + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + if (map_table) + bits = map_table[bits]; + else + while (run_length-- > 0 && pixels_read < dbuf_len) + { + *destbuf++ = bits; + pixels_read++; + } + } + } + } - if (*(*srcbuf)++) - printf("DVBSub error: line overflow\n"); + if (*(*srcbuf)++) + mprint("DVBSub error: line overflow\n"); - return pixels_read; + return pixels_read; } - - -static void dvbsub_parse_pixel_data_block(void *dvb_ctx, DVBSubObjectDisplay *display, - const uint8_t *buf, int buf_size, int top_bottom, int non_mod) +static void dvbsub_parse_pixel_data_block(void *dvb_ctx, + DVBSubObjectDisplay *display, const uint8_t *buf, int buf_size, + int top_bottom, int non_mod) { - DVBSubContext *ctx = (DVBSubContext *)dvb_ctx; + DVBSubContext *ctx = (DVBSubContext *) dvb_ctx; - DVBSubRegion *region = get_region(ctx, display->region_id); - const uint8_t *buf_end = buf + buf_size; - uint8_t *pbuf; - int x_pos, y_pos; - int i; + DVBSubRegion *region = get_region(ctx, display->region_id); + const uint8_t *buf_end = buf + buf_size; + uint8_t *pbuf; + int x_pos, y_pos; + int i; - uint8_t map2to4[] = { 0x0, 0x7, 0x8, 0xf}; - uint8_t map2to8[] = {0x00, 0x77, 0x88, 0xff}; - uint8_t map4to8[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; - uint8_t *map_table; + uint8_t map2to4[] = { 0x0, 0x7, 0x8, 0xf }; + uint8_t map2to8[] = { 0x00, 0x77, 0x88, 0xff }; + uint8_t map4to8[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; + uint8_t *map_table; - if (region == 0) - return; + if (region == 0) + return; - pbuf = region->pbuf; - region->dirty = 1; + pbuf = region->pbuf; + region->dirty = 1; - x_pos = display->x_pos; - y_pos = display->y_pos; + x_pos = display->x_pos; + y_pos = display->y_pos; - y_pos += top_bottom; + y_pos += top_bottom; - while (buf < buf_end) { - if ((*buf!=0xf0 && x_pos >= region->width) || y_pos >= region->height) { - printf("Invalid object location! %d-%d %d-%d %02x\n", x_pos, region->width, y_pos, region->height, *buf); - return; - } + while (buf < buf_end) + { + if ((*buf != 0xf0 && x_pos >= region->width) || y_pos >= region->height) + { + mprint("Invalid object location! %d-%d %d-%d %02x\n", x_pos, + region->width, y_pos, region->height, *buf); + return; + } - switch (*buf++) { - case 0x10: - if (region->depth == 8) - map_table = map2to8; - else if (region->depth == 4) - map_table = map2to4; - else - map_table = NULL; + switch (*buf++) + { + case 0x10: + if (region->depth == 8) + map_table = map2to8; + else if (region->depth == 4) + map_table = map2to4; + else + map_table = NULL; - x_pos = dvbsub_read_2bit_string(pbuf + (y_pos * region->width), - region->width, &buf, buf_end - buf, - non_mod, map_table, x_pos); - break; - case 0x11: - if (region->depth < 4) { - printf("4-bit pixel string in %d-bit region!\n", region->depth); - return; - } + x_pos = dvbsub_read_2bit_string(pbuf + (y_pos * region->width), + region->width, &buf, buf_end - buf, non_mod, map_table, + x_pos); + break; + case 0x11: + if (region->depth < 4) + { + mprint("4-bit pixel string in %d-bit region!\n", + region->depth); + return; + } - if (region->depth == 8) - map_table = map4to8; - else - map_table = NULL; + if (region->depth == 8) + map_table = map4to8; + else + map_table = NULL; - x_pos = dvbsub_read_4bit_string(pbuf + (y_pos * region->width), - region->width, &buf, buf_end - buf, - non_mod, map_table, x_pos); - break; - case 0x12: - if (region->depth < 8) { - printf("8-bit pixel string in %d-bit region!\n", region->depth); - return; - } + x_pos = dvbsub_read_4bit_string(pbuf + (y_pos * region->width), + region->width, &buf, buf_end - buf, non_mod, map_table, + x_pos); + break; + case 0x12: + if (region->depth < 8) + { + mprint("8-bit pixel string in %d-bit region!\n", + region->depth); + return; + } - x_pos = dvbsub_read_8bit_string(pbuf + (y_pos * region->width), - region->width, &buf, buf_end - buf, - non_mod, NULL, x_pos); - break; + x_pos = dvbsub_read_8bit_string(pbuf + (y_pos * region->width), + region->width, &buf, buf_end - buf, non_mod, NULL, + x_pos); + break; - case 0x20: - map2to4[0] = (*buf) >> 4; - map2to4[1] = (*buf++) & 0xf; - map2to4[2] = (*buf) >> 4; - map2to4[3] = (*buf++) & 0xf; - break; - case 0x21: - for (i = 0; i < 4; i++) - map2to8[i] = *buf++; - break; - case 0x22: - for (i = 0; i < 16; i++) - map4to8[i] = *buf++; - break; + case 0x20: + map2to4[0] = (*buf) >> 4; + map2to4[1] = (*buf++) & 0xf; + map2to4[2] = (*buf) >> 4; + map2to4[3] = (*buf++) & 0xf; + break; + case 0x21: + for (i = 0; i < 4; i++) + map2to8[i] = *buf++; + break; + case 0x22: + for (i = 0; i < 16; i++) + map4to8[i] = *buf++; + break; - case 0xf0: - x_pos = display->x_pos; - y_pos += 2; - break; - default: - printf("Unknown/unsupported pixel block 0x%x\n", *(buf-1)); - } - } + case 0xf0: + x_pos = display->x_pos; + y_pos += 2; + break; + default: + mprint("Unknown/unsupported pixel block 0x%x\n", *(buf - 1)); + /* no break */ + } + } } -static void dvbsub_parse_object_segment(void *dvb_ctx, - const uint8_t *buf, int buf_size) +static void dvbsub_parse_object_segment(void *dvb_ctx, const uint8_t *buf, + int buf_size) { - DVBSubContext *ctx = (DVBSubContext*)dvb_ctx; + DVBSubContext *ctx = (DVBSubContext*) dvb_ctx; - const uint8_t *buf_end = buf + buf_size; - int object_id; - DVBSubObject *object; - DVBSubObjectDisplay *display; - int top_field_len, bottom_field_len; + const uint8_t *buf_end = buf + buf_size; + int object_id; + DVBSubObject *object; + DVBSubObjectDisplay *display; + int top_field_len, bottom_field_len; - int coding_method, non_modifying_color; + int coding_method, non_modifying_color; - object_id = RB16(buf); - buf += 2; + object_id = RB16(buf); + buf += 2; - object = get_object(ctx, object_id); + object = get_object(ctx, object_id); - if (!object) - return; + if (!object) + return; - coding_method = ((*buf) >> 2) & 3; - non_modifying_color = ((*buf++) >> 1) & 1; + coding_method = ((*buf) >> 2) & 3; + non_modifying_color = ((*buf++) >> 1) & 1; - if (coding_method == 0) { - top_field_len = RB16(buf); - buf += 2; - bottom_field_len = RB16(buf); - buf += 2; + if (coding_method == 0) + { + top_field_len = RB16(buf); + buf += 2; + bottom_field_len = RB16(buf); + buf += 2; - if (buf + top_field_len + bottom_field_len > buf_end) { - printf( "Field data size too large\n"); - return; - } + if (buf + top_field_len + bottom_field_len > buf_end) + { + mprint("Field data size too large\n"); + return; + } - for (display = object->display_list; display; display = display->object_list_next) { - const uint8_t *block = buf; - int bfl = bottom_field_len; + for (display = object->display_list; display; + display = display->object_list_next) + { + const uint8_t *block = buf; + int bfl = bottom_field_len; - dvbsub_parse_pixel_data_block(dvb_ctx, display, block, top_field_len, 0, - non_modifying_color); + dvbsub_parse_pixel_data_block(dvb_ctx, display, block, + top_field_len, 0, non_modifying_color); - if (bottom_field_len > 0) - block = buf + top_field_len; - else - bfl = top_field_len; + if (bottom_field_len > 0) + block = buf + top_field_len; + else + bfl = top_field_len; - dvbsub_parse_pixel_data_block(dvb_ctx, display, block, bfl, 1, - non_modifying_color); - } + dvbsub_parse_pixel_data_block(dvb_ctx, display, block, bfl, 1, + non_modifying_color); + } - } else if (coding_method == 1) { - printf( "FIXME support for sring coding standard\n"); - } else { - printf( "Unknown object coding %d\n", coding_method); - } + } + else if (coding_method == 1) + { + mprint("FIXME support for sring coding standard\n"); + } + else + { + mprint("Unknown object coding %d\n", coding_method); + } } -static int dvbsub_parse_clut_segment(void *dvb_ctx, - const uint8_t *buf, int buf_size) +static int dvbsub_parse_clut_segment(void *dvb_ctx, const uint8_t *buf, + int buf_size) { - DVBSubContext *ctx = (DVBSubContext*)dvb_ctx; + DVBSubContext *ctx = (DVBSubContext*) dvb_ctx; - const uint8_t *buf_end = buf + buf_size; - int i, clut_id; - int version; - DVBSubCLUT *clut; - int entry_id, depth , full_range; - int y, cr, cb, alpha; - int r, g, b, r_add, g_add, b_add; + const uint8_t *buf_end = buf + buf_size; + int clut_id; + int version; + DVBSubCLUT *clut; + int entry_id, depth, full_range; + int y, cr, cb, alpha; + int r, g, b, r_add, g_add, b_add; - printf("DVB clut packet:\n"); + clut_id = *buf++; + version = ((*buf) >> 4) & 15; + buf += 1; - for (i=0; i < buf_size; i++) { - printf("%02x ", buf[i]); - if (i % 16 == 15) - printf("\n"); - } + clut = get_clut(ctx, clut_id); - if (i % 16) - printf("\n"); + if (!clut) + { + clut = (DVBSubCLUT*) malloc(sizeof(DVBSubCLUT)); - clut_id = *buf++; - version = ((*buf)>>4)&15; - buf += 1; + memcpy(clut, &default_clut, sizeof(DVBSubCLUT)); - clut = get_clut(ctx, clut_id); + clut->id = clut_id; + clut->version = -1; - if (!clut) { - clut = (DVBSubCLUT*)malloc(sizeof(DVBSubCLUT)); + clut->next = ctx->clut_list; + ctx->clut_list = clut; + } - memcpy(clut, &default_clut, sizeof(DVBSubCLUT)); + if (clut->version != version) + { - clut->id = clut_id; - clut->version = -1; + clut->version = version; - clut->next = ctx->clut_list; - ctx->clut_list = clut; - } + while (buf + 4 < buf_end) + { + entry_id = *buf++; - if (clut->version != version) { + depth = (*buf) & 0xe0; - clut->version = version; + if (depth == 0) + { + mprint("Invalid clut depth 0x%x!\n", *buf); + return 0; + } - while (buf + 4 < buf_end) { - entry_id = *buf++; + full_range = (*buf++) & 1; - depth = (*buf) & 0xe0; + if (full_range) + { + y = *buf++; + cr = *buf++; + cb = *buf++; + alpha = *buf++; + } + else + { + y = buf[0] & 0xfc; + cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4; + cb = (buf[1] << 2) & 0xf0; + alpha = (buf[1] << 6) & 0xc0; - if (depth == 0) { - printf( "Invalid clut depth 0x%x!\n", *buf); - return 0; - } + buf += 2; + } - full_range = (*buf++) & 1; + if (y == 0) + alpha = 0xff; - if (full_range) { - y = *buf++; - cr = *buf++; - cb = *buf++; - alpha = *buf++; - } else { - y = buf[0] & 0xfc; - cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4; - cb = (buf[1] << 2) & 0xf0; - alpha = (buf[1] << 6) & 0xc0; + YUV_TO_RGB1_CCIR(cb, cr); + YUV_TO_RGB2_CCIR(r, g, b, y); - buf += 2; - } + if (!!(depth & 0x80) + !!(depth & 0x40) + !!(depth & 0x20) > 1) + { + mprint("More than one bit level marked: %x\n", depth); + } - if (y == 0) - alpha = 0xff; - - YUV_TO_RGB1_CCIR(cb, cr); - YUV_TO_RGB2_CCIR(r, g, b, y); - - printf("clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha); - if (!!(depth & 0x80) + !!(depth & 0x40) + !!(depth & 0x20) > 1) { - printf("More than one bit level marked: %x\n", depth); - } - - if (depth & 0x80) - clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha); - else if (depth & 0x40) - clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha); - else if (depth & 0x20) - clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha); - } - } - return 0; + if (depth & 0x80) + clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha); + else if (depth & 0x40) + clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha); + else if (depth & 0x20) + clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha); + } + } + return 0; } - -static void dvbsub_parse_region_segment(void*dvb_ctx, - const uint8_t *buf, int buf_size) +static void dvbsub_parse_region_segment(void*dvb_ctx, const uint8_t *buf, + int buf_size) { - DVBSubContext *ctx = (DVBSubContext *)dvb_ctx; + DVBSubContext *ctx = (DVBSubContext *) dvb_ctx; - const uint8_t *buf_end = buf + buf_size; - int region_id, object_id; - int version; - DVBSubRegion *region; - DVBSubObject *object; - DVBSubObjectDisplay *display; - int fill; + const uint8_t *buf_end = buf + buf_size; + int region_id, object_id; + int version; + DVBSubRegion *region; + DVBSubObject *object; + DVBSubObjectDisplay *display; + int fill; - if (buf_size < 10) - return; + if (buf_size < 10) + return; - region_id = *buf++; - version = ((*buf)>>4) & 15; + region_id = *buf++; + version = ((*buf) >> 4) & 15; - region = get_region(ctx, region_id); + region = get_region(ctx, region_id); - if (!region) { - region = (struct DVBSubRegion*) malloc(sizeof(struct DVBSubRegion)); - memset(region,0,sizeof(struct DVBSubRegion)); + if (!region) + { + region = (struct DVBSubRegion*) malloc(sizeof(struct DVBSubRegion)); + memset(region, 0, sizeof(struct DVBSubRegion)); - region->id = region_id; - region->version = version; + region->id = region_id; + region->version = version; - region->next = ctx->region_list; - ctx->region_list = region; - } else if(version == region->version) - return; - fill = ((*buf++) >> 3) & 1; + region->next = ctx->region_list; + ctx->region_list = region; + } + else if (version == region->version) + return; + fill = ((*buf++) >> 3) & 1; - region->width = RB16(buf); - buf += 2; - region->height = RB16(buf); - buf += 2; + region->width = RB16(buf); + buf += 2; + region->height = RB16(buf); + buf += 2; - if (region->width * region->height != region->buf_size) { - free(region->pbuf); + if (region->width * region->height != region->buf_size) + { + free(region->pbuf); - region->buf_size = region->width * region->height; + region->buf_size = region->width * region->height; - region->pbuf = (uint8_t*)malloc(region->buf_size); + region->pbuf = (uint8_t*) malloc(region->buf_size); - fill = 1; - region->dirty = 0; - } + fill = 1; + region->dirty = 0; + } - region->depth = 1 << (((*buf++) >> 2) & 7); - if(region->depth<2 || region->depth>8){ - printf( "region depth %d is invalid\n", region->depth); - region->depth= 4; - } - region->clut = *buf++; + region->depth = 1 << (((*buf++) >> 2) & 7); + if (region->depth < 2 || region->depth > 8) + { + mprint("region depth %d is invalid\n", region->depth); + region->depth = 4; + } + region->clut = *buf++; - if (region->depth == 8) { - region->bgcolor = *buf++; - buf += 1; - } else { - buf += 1; + if (region->depth == 8) + { + region->bgcolor = *buf++; + buf += 1; + } + else + { + buf += 1; - if (region->depth == 4) - region->bgcolor = (((*buf++) >> 4) & 15); - else - region->bgcolor = (((*buf++) >> 2) & 3); - } + if (region->depth == 4) + region->bgcolor = (((*buf++) >> 4) & 15); + else + region->bgcolor = (((*buf++) >> 2) & 3); + } - printf("Region %d, (%dx%d)\n", region_id, region->width, region->height); + if (fill) + memset(region->pbuf, region->bgcolor, region->buf_size); - if (fill) { - memset(region->pbuf, region->bgcolor, region->buf_size); - printf( "Fill region (%d)\n", region->bgcolor); - } + delete_region_display_list(ctx, region); - delete_region_display_list(ctx, region); + while (buf + 5 < buf_end) + { + object_id = RB16(buf); + buf += 2; - while (buf + 5 < buf_end) { - object_id = RB16(buf); - buf += 2; + object = get_object(ctx, object_id); - object = get_object(ctx, object_id); + if (!object) + { + object = (struct DVBSubObject*) malloc(sizeof(struct DVBSubObject)); + memset(object, 0, sizeof(struct DVBSubObject)); - if (!object) { - object = (struct DVBSubObject*)malloc(sizeof(struct DVBSubObject)); - memset(object,0,sizeof(struct DVBSubObject)); + object->id = object_id; + object->next = ctx->object_list; + ctx->object_list = object; + } - object->id = object_id; - object->next = ctx->object_list; - ctx->object_list = object; - } + object->type = (*buf) >> 6; - object->type = (*buf) >> 6; + display = (struct DVBSubObjectDisplay*) malloc( + sizeof(struct DVBSubObjectDisplay)); + memset(display, 0, sizeof(struct DVBSubObjectDisplay)); - display = (struct DVBSubObjectDisplay*)malloc(sizeof(struct DVBSubObjectDisplay)); - memset(display,0,sizeof(struct DVBSubObjectDisplay)); + display->object_id = object_id; + display->region_id = region_id; - display->object_id = object_id; - display->region_id = region_id; + display->x_pos = RB16(buf) & 0xfff; + buf += 2; + display->y_pos = RB16(buf) & 0xfff; + buf += 2; - display->x_pos = RB16(buf) & 0xfff; - buf += 2; - display->y_pos = RB16(buf) & 0xfff; - buf += 2; + if ((object->type == 1 || object->type == 2) && buf + 1 < buf_end) + { + display->fgcolor = *buf++; + display->bgcolor = *buf++; + } - if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) { - display->fgcolor = *buf++; - display->bgcolor = *buf++; - } + display->region_list_next = region->display_list; + region->display_list = display; - display->region_list_next = region->display_list; - region->display_list = display; - - display->object_list_next = object->display_list; - object->display_list = display; - } + display->object_list_next = object->display_list; + object->display_list = display; + } } -static void dvbsub_parse_page_segment(void *dvb_ctx, - const uint8_t *buf, int buf_size) +static void dvbsub_parse_page_segment(void *dvb_ctx, const uint8_t *buf, + int buf_size) { - DVBSubContext *ctx = (DVBSubContext*)dvb_ctx; - DVBSubRegionDisplay *display; - DVBSubRegionDisplay *tmp_display_list, **tmp_ptr; + DVBSubContext *ctx = (DVBSubContext*) dvb_ctx; + DVBSubRegionDisplay *display; + DVBSubRegionDisplay *tmp_display_list, **tmp_ptr; - const uint8_t *buf_end = buf + buf_size; - int region_id; - int page_state; - int timeout; - int version; + const uint8_t *buf_end = buf + buf_size; + int region_id; + int page_state; + int timeout; + int version; - if (buf_size < 1) - return; + if (buf_size < 1) + return; - timeout = *buf++; - version = ((*buf)>>4) & 15; - page_state = ((*buf++) >> 2) & 3; + timeout = *buf++; + version = ((*buf) >> 4) & 15; + page_state = ((*buf++) >> 2) & 3; - //if version same mean we are already updated - if (ctx->version == version) - { - return; - } + //if version same mean we are already updated + if (ctx->version == version) + { + return; + } - ctx->time_out = timeout; - ctx->version = version; + ctx->time_out = timeout; + ctx->version = version; - printf( "Page time out %ds, state %d\n", ctx->time_out, page_state); + if (page_state == 1 || page_state == 2) + { + delete_regions(ctx); + delete_objects(ctx); + delete_cluts(ctx); + } - if (page_state == 1 || page_state == 2) { - delete_regions(ctx); - delete_objects(ctx); - delete_cluts(ctx); - } + tmp_display_list = ctx->display_list; + ctx->display_list = NULL; - tmp_display_list = ctx->display_list; - ctx->display_list = NULL; + while (buf + 5 < buf_end) + { + region_id = *buf++; + buf += 1; - while (buf + 5 < buf_end) { - region_id = *buf++; - buf += 1; + display = tmp_display_list; + tmp_ptr = &tmp_display_list; - display = tmp_display_list; - tmp_ptr = &tmp_display_list; + while (display && display->region_id != region_id) + { + tmp_ptr = &display->next; + display = display->next; + } - while (display && display->region_id != region_id) { - tmp_ptr = &display->next; - display = display->next; - } + if (!display) + { + display = (struct DVBSubRegionDisplay*) malloc( + sizeof(struct DVBSubRegionDisplay)); + memset(display, 0, sizeof(struct DVBSubRegionDisplay)); + } - if (!display) - { - display = (struct DVBSubRegionDisplay*)malloc(sizeof(struct DVBSubRegionDisplay)); - memset(display,0,sizeof(struct DVBSubRegionDisplay)); - } + display->region_id = region_id; + display->x_pos = RB16(buf); + buf += 2; + display->y_pos = RB16(buf); + buf += 2; - display->region_id = region_id; + *tmp_ptr = display->next; - display->x_pos = RB16(buf); - buf += 2; - display->y_pos = RB16(buf); - buf += 2; + display->next = ctx->display_list; + ctx->display_list = display; - *tmp_ptr = display->next; + } - display->next = ctx->display_list; - ctx->display_list = display; + while (tmp_display_list) + { + display = tmp_display_list; - printf( "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos); - } + tmp_display_list = display->next; - while (tmp_display_list) { - display = tmp_display_list; - - tmp_display_list = display->next; - - free(display); - } + free(display); + } } - #ifdef DEBUG static void save_display_set(DVBSubContext *ctx) { - DVBSubRegion *region; - DVBSubRegionDisplay *display; - DVBSubCLUT *clut; - uint32_t *clut_table; - int x_pos, y_pos, width, height; - int x, y, y_off, x_off; - uint32_t *pbuf; - char filename[32]; - static int fileno_index = 0; + DVBSubRegion *region; + DVBSubRegionDisplay *display; + DVBSubCLUT *clut; + uint32_t *clut_table; + int x_pos, y_pos, width, height; + int x, y, y_off, x_off; + uint32_t *pbuf; + char *filename; + void *sp = ctx->out->spupng_data; + long long start = get_visible_start(); + x_pos = -1; + y_pos = -1; + width = 0; + height = 0; - x_pos = -1; - y_pos = -1; - width = 0; - height = 0; + filename = get_spupng_filename(sp); + inc_spupng_fileindex(sp); + write_sputag(sp, start, start + ctx->time_out); + for (display = ctx->display_list; display; display = display->next) + { + region = get_region(ctx, display->region_id); - for (display = ctx->display_list; display; display = display->next) { - region = get_region(ctx, display->region_id); + if (x_pos == -1) + { + x_pos = display->x_pos; + y_pos = display->y_pos; + width = region->width; + height = region->height; + } + else + { + if (display->x_pos < x_pos) + { + width += (x_pos - display->x_pos); + x_pos = display->x_pos; + } - if (x_pos == -1) { - x_pos = display->x_pos; - y_pos = display->y_pos; - width = region->width; - height = region->height; - } else { - if (display->x_pos < x_pos) { - width += (x_pos - display->x_pos); - x_pos = display->x_pos; - } + if (display->y_pos < y_pos) + { + height += (y_pos - display->y_pos); + y_pos = display->y_pos; + } - if (display->y_pos < y_pos) { - height += (y_pos - display->y_pos); - y_pos = display->y_pos; - } + if (display->x_pos + region->width > x_pos + width) + { + width = display->x_pos + region->width - x_pos; + } - if (display->x_pos + region->width > x_pos + width) { - width = display->x_pos + region->width - x_pos; - } + if (display->y_pos + region->height > y_pos + height) + { + height = display->y_pos + region->height - y_pos; + } + } + } - if (display->y_pos + region->height > y_pos + height) { - height = display->y_pos + region->height - y_pos; - } - } - } + if (x_pos >= 0) + { - if (x_pos >= 0) { + pbuf = (uint32_t*) malloc(width * height * 4); + memset(pbuf, 0x0, width * height * 4); - pbuf = (uint32_t*)malloc(width * height * 4); - memset(pbuf,0x0,width * height * 4); + for (display = ctx->display_list; display; display = display->next) + { + region = get_region(ctx, display->region_id); + x_off = display->x_pos - x_pos; + y_off = display->y_pos - y_pos; - for (display = ctx->display_list; display; display = display->next) { - region = get_region(ctx, display->region_id); + clut = get_clut(ctx, region->clut); - x_off = display->x_pos - x_pos; - y_off = display->y_pos - y_pos; + if (clut == 0) + clut = &default_clut; - clut = get_clut(ctx, region->clut); + switch (region->depth) + { + case 2: + clut_table = clut->clut4; + break; + case 8: + clut_table = clut->clut256; + break; + case 4: + default: + clut_table = clut->clut16; + break; + } - if (clut == 0) - clut = &default_clut; + for (y = 0; y < region->height; y++) + { + for (x = 0; x < region->width; x++) + { + pbuf[((y + y_off) * width) + x_off + x] = + clut_table[region->pbuf[y * region->width + x]]; + } + } - switch (region->depth) { - case 2: - clut_table = clut->clut4; - break; - case 8: - clut_table = clut->clut256; - break; - case 4: - default: - clut_table = clut->clut16; - break; - } + } - for (y = 0; y < region->height; y++) { - for (x = 0; x < region->width; x++) { - pbuf[((y + y_off) * width) + x_off + x] = - clut_table[region->pbuf[y * region->width + x]]; - } - } + png_save(filename, pbuf, width, height); + //png_save1(filename, region->pbuf, region->width, region->height,clut->clut16); - } + free(pbuf); + } - snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index); - - png_save(filename, pbuf, width, height); - - free(pbuf); - } - - fileno_index++; } #endif static void dvbsub_parse_display_definition_segment(void *dvb_ctx, - const uint8_t *buf, - int buf_size) + const uint8_t *buf, int buf_size) { - DVBSubContext *ctx = (DVBSubContext *)dvb_ctx; - DVBSubDisplayDefinition *display_def = ctx->display_definition; - int dds_version, info_byte; + DVBSubContext *ctx = (DVBSubContext *) dvb_ctx; + DVBSubDisplayDefinition *display_def = ctx->display_definition; + int dds_version, info_byte; - if (buf_size < 5) - return; + if (buf_size < 5) + return; - info_byte = bytestream_get_byte(&buf); - dds_version = info_byte >> 4; - if (display_def && display_def->version == dds_version) - return; // already have this display definition version + info_byte = bytestream_get_byte(&buf); + dds_version = info_byte >> 4; + if (display_def && display_def->version == dds_version) + return; // already have this display definition version - if (!display_def) { - display_def = (struct DVBSubDisplayDefinition*)malloc(sizeof(*display_def)); - memset(display_def,0,sizeof(*display_def)); - ctx->display_definition = display_def; - } - if (!display_def) - return; + if (!display_def) + { + display_def = (struct DVBSubDisplayDefinition*) malloc( + sizeof(*display_def)); + memset(display_def, 0, sizeof(*display_def)); + ctx->display_definition = display_def; + } + if (!display_def) + return; - display_def->version = dds_version; - display_def->x = 0; - display_def->y = 0; - display_def->width = bytestream_get_be16(&buf) + 1; - display_def->height = bytestream_get_be16(&buf) + 1; + display_def->version = dds_version; + display_def->x = 0; + display_def->y = 0; + display_def->width = bytestream_get_be16(&buf) + 1; + display_def->height = bytestream_get_be16(&buf) + 1; - if (buf_size < 13) - return; + if (buf_size < 13) + return; - if (info_byte & 1<<3) { // display_window_flag - display_def->x = bytestream_get_be16(&buf); - display_def->width = bytestream_get_be16(&buf) - display_def->x + 1; - display_def->y = bytestream_get_be16(&buf); - display_def->height = bytestream_get_be16(&buf) - display_def->y + 1; - } + if (info_byte & 1 << 3) + { // display_window_flag + display_def->x = bytestream_get_be16(&buf); + display_def->width = bytestream_get_be16(&buf) - display_def->x + 1; + display_def->y = bytestream_get_be16(&buf); + display_def->height = bytestream_get_be16(&buf) - display_def->y + 1; + } } static int dvbsub_display_end_segment(void *dvb_ctx, const uint8_t *buf, - int buf_size) + int buf_size) { - DVBSubContext *ctx = (DVBSubContext *)dvb_ctx; + DVBSubContext *ctx = (DVBSubContext *) dvb_ctx; - DVBSubRegion *region; - DVBSubRegionDisplay *display; - DVBSubCLUT *clut; - int i; + DVBSubRegion *region; + DVBSubRegionDisplay *display; + DVBSubCLUT *clut; + int i; + for (display = ctx->display_list; display; display = display->next) + { + region = get_region(ctx, display->region_id); + } + i = 0; - for (display = ctx->display_list; display; display = display->next) - { - region = get_region(ctx, display->region_id); - } + for (display = ctx->display_list; display; display = display->next) + { + region = get_region(ctx, display->region_id); - i = 0; + if (!region) + continue; - for (display = ctx->display_list; display; display = display->next) { - region = get_region(ctx, display->region_id); + if (!region->dirty) + continue; + clut = get_clut(ctx, region->clut); - if (!region) - continue; + if (!clut) + clut = &default_clut; - if (!region->dirty) - continue; - clut = get_clut(ctx, region->clut); - - if (!clut) - clut = &default_clut; - - i++; - } + i++; + } #ifdef DEBUG - save_display_set(ctx); + if (ctx->object_list) + { + save_display_set(ctx); + } #endif - return 1; + return 1; } /** * @param dvb_ctx PreInitialized DVB context using DVB * @param data output subtitle data, to be implemented - * @param data_size Output subtitle data size. pass the pointer to an intiger, NOT to be NULL. - * @param buf buffer containg segment data, first sync byte needto 0x0f. + * @param data_size Output subtitle data size. pass the pointer to an integer, NOT to be NULL. + * @param buf buffer containing segment data, first sync byte need to 0x0f. * does not include data_identifier and subtitle_stream_id. * @param buf_size size of buf buffer * * @return -1 on error */ -int dvbsub_decode(void *dvb_ctx, - void *data, int *data_size, - const unsigned char *buf, int buf_size) +int dvbsub_decode(void *dvb_ctx, void *data, int *data_size, + const unsigned char *buf, int buf_size) { - DVBSubContext *ctx = (DVBSubContext *)dvb_ctx; + DVBSubContext *ctx = (DVBSubContext *) dvb_ctx; // AVSubtitle *sub = data; - const uint8_t *p, *p_end; - int segment_type; - int page_id; - int segment_length; - int ret; - int got_segment = 0; + const uint8_t *p, *p_end; + int segment_type; + int page_id; + int segment_length; + int ret; + int got_segment = 0; + if (buf_size <= 6 || *buf != 0x0f) + { + mprint("incomplete or broken packet"); + return -1; + } - if (buf_size <= 6 || *buf != 0x0f) { - printf( "incomplete or broken packet"); - return -1; - } + p = buf; + p_end = buf + buf_size; - p = buf; - p_end = buf + buf_size; + while (p_end - p >= 6 && *p == 0x0f) + { + p += 1; + segment_type = *p++; + page_id = RB16(p); + p += 2; + segment_length = RB16(p); + p += 2; - while (p_end - p >= 6 && *p == 0x0f) { - p += 1; - segment_type = *p++; - page_id = RB16(p); - p += 2; - segment_length = RB16(p); - p += 2; + if (p_end - p < segment_length) + { + mprint("incomplete or broken packet"); + return -1; + } - if (p_end - p < segment_length) { - printf( "incomplete or broken packet"); - return -1; - } + if (page_id == ctx->composition_id || page_id == ctx->ancillary_id + || ctx->composition_id == -1 || ctx->ancillary_id == -1) + { + switch (segment_type) + { + case DVBSUB_PAGE_SEGMENT: + dvbsub_parse_page_segment(dvb_ctx, p, segment_length); + got_segment |= 1; + break; + case DVBSUB_REGION_SEGMENT: + dvbsub_parse_region_segment(dvb_ctx, p, segment_length); + got_segment |= 2; + break; + case DVBSUB_CLUT_SEGMENT: + ret = dvbsub_parse_clut_segment(dvb_ctx, p, segment_length); + if (ret < 0) + return ret; + got_segment |= 4; + break; + case DVBSUB_OBJECT_SEGMENT: + dvbsub_parse_object_segment(dvb_ctx, p, segment_length); + got_segment |= 8; + break; + case DVBSUB_DISPLAYDEFINITION_SEGMENT: + dvbsub_parse_display_definition_segment(dvb_ctx, p, + segment_length); + break; + case DVBSUB_DISPLAY_SEGMENT: + *data_size = dvbsub_display_end_segment(dvb_ctx, p, + segment_length); + got_segment |= 16; + break; + default: + mprint( + "Subtitling segment type 0x%x, page id %d, length %d\n", + segment_type, page_id, segment_length); + break; + } + } - if (page_id == ctx->composition_id || page_id == ctx->ancillary_id || - ctx->composition_id == -1 || ctx->ancillary_id == -1) { - switch (segment_type) { - case DVBSUB_PAGE_SEGMENT: - dvbsub_parse_page_segment(dvb_ctx, p, segment_length); - got_segment |= 1; - break; - case DVBSUB_REGION_SEGMENT: - dvbsub_parse_region_segment(dvb_ctx, p, segment_length); - got_segment |= 2; - break; - case DVBSUB_CLUT_SEGMENT: - ret = dvbsub_parse_clut_segment(dvb_ctx, p, segment_length); - if (ret < 0) return ret; - got_segment |= 4; - break; - case DVBSUB_OBJECT_SEGMENT: - dvbsub_parse_object_segment(dvb_ctx, p, segment_length); - got_segment |= 8; - break; - case DVBSUB_DISPLAYDEFINITION_SEGMENT: - dvbsub_parse_display_definition_segment(dvb_ctx, p, segment_length); - break; - case DVBSUB_DISPLAY_SEGMENT: - *data_size = dvbsub_display_end_segment(dvb_ctx, p, segment_length); - got_segment |= 16; - break; - default: - printf( "Subtitling segment type 0x%x, page id %d, length %d\n", - segment_type, page_id, segment_length); - break; - } - } + p += segment_length; + } + // Some streams do not send a display segment but if we have all the other + // segments then we need no further data. + if (got_segment == 15) + *data_size = dvbsub_display_end_segment(dvb_ctx, p, 0); - p += segment_length; - } - // Some streams do not send a display segment but if we have all the other - // segments then we need no further data. - if (got_segment == 15) - *data_size = dvbsub_display_end_segment(dvb_ctx, p, 0); - - return p - buf; + return p - buf; } /** * @func parse_dvb_description @@ -1645,50 +1888,63 @@ int dvbsub_decode(void *dvb_ctx, * @return return -1 if invalid data found other wise 0 if everything goes well * errno is set is to EINVAL if invalid data is found */ -int parse_dvb_description (struct dvb_config* cfg,unsigned char*data,unsigned int len) +int parse_dvb_description(struct dvb_config* cfg, unsigned char*data, + unsigned int len) { - int i = 0; - int j = 0; - /* 8 bytes per DVB subtitle substream d2: - * ISO_639_language_code (3 bytes), - * subtitling_type (1 byte), - * composition_page_id (2 bytes), - * ancillary_page_id (2 bytes) - */ + int i = 0; + int j = 0; + /* 8 bytes per DVB subtitle substream d2: + * ISO_639_language_code (3 bytes), + * subtitling_type (1 byte), + * composition_page_id (2 bytes), + * ancillary_page_id (2 bytes) + */ - cfg->n_language = len/8; + cfg->n_language = len / 8; - if (len > 0 && len % 8 != 0) - { - errno = EINVAL; - return -1; - } + if (len > 0 && len % 8 != 0) + { + errno = EINVAL; + return -1; + } - if (cfg->n_language > 1) - { - printf("DVB subtitles with multiple languages"); - } + if (cfg->n_language > 1) + { + mprint("DVB subtitles with multiple languages"); + } - if (cfg->n_language > MAX_LANGUAGE_PER_DESC) - { - printf("not supported more then %d language",MAX_LANGUAGE_PER_DESC); - } + if (cfg->n_language > MAX_LANGUAGE_PER_DESC) + { + mprint("not supported more then %d language", MAX_LANGUAGE_PER_DESC); + } - for (i = 0; i < cfg->n_language; i++,data += i*8) - { - /* setting language to undefined if not found in language lkup table */ - for(j = 0,cfg->lang_index[i] = 0;dvb_language[j] != NULL;j++) - { - if(!strncmp((const char*)(data),dvb_language[j],3)) - cfg->lang_index[i] = j; - } - cfg->sub_type[i] = data[3]; - cfg->composition_id[i] = RB16(data + 4); - cfg->ancillary_id[i] = RB16(data + 6); + for (i = 0; i < cfg->n_language; i++, data += i * 8) + { + /* setting language to undefined if not found in language lkup table */ + for (j = 0, cfg->lang_index[i] = 0; dvb_language[j] != NULL ; j++) + { + if (!strncmp((const char*) (data), dvb_language[j], 3)) + cfg->lang_index[i] = j; + } + cfg->sub_type[i] = data[3]; + cfg->composition_id[i] = RB16(data + 4); + cfg->ancillary_id[i] = RB16(data + 6); - } + } - printf("lang %d %s\n",cfg->lang_index[0],dvb_language[cfg->lang_index[0]]); - printf("comp %hd anci %hd stype %hhd\n",cfg->composition_id[0],cfg->ancillary_id[0],cfg->sub_type[0]); - return 0; + return 0; +} +/* + * @func dvbsub_set_write the output structure in dvb + * set ccx_s_write structure in dvb_ctx + * + * @param dvb_ctx context of dvb which was returned by dvbsub_init_decoder + * + * @param out output context returned by init_write + * + */ +void dvbsub_set_write(void *dvb_ctx, struct ccx_s_write *out) +{ + DVBSubContext *ctx = (DVBSubContext *) dvb_ctx; + ctx->out = out; } diff --git a/src/dvb_subtitle_decoder.h b/src/dvb_subtitle_decoder.h index 9f53cc39..ed0f4e19 100644 --- a/src/dvb_subtitle_decoder.h +++ b/src/dvb_subtitle_decoder.h @@ -18,6 +18,7 @@ #define MAX_LANGUAGE_PER_DESC 5 +#include "ccextractor.h" #ifdef __cplusplus extern "C" { @@ -25,17 +26,16 @@ extern "C" struct dvb_config { - unsigned char n_language; - unsigned int lang_index[MAX_LANGUAGE_PER_DESC]; - /* subtitle type */ - unsigned char sub_type[MAX_LANGUAGE_PER_DESC]; - /* composition page id */ - unsigned short composition_id[MAX_LANGUAGE_PER_DESC]; - /* ancillary_page_id */ - unsigned short ancillary_id[MAX_LANGUAGE_PER_DESC]; + unsigned char n_language; + unsigned int lang_index[MAX_LANGUAGE_PER_DESC]; + /* subtitle type */ + unsigned char sub_type[MAX_LANGUAGE_PER_DESC]; + /* composition page id */ + unsigned short composition_id[MAX_LANGUAGE_PER_DESC]; + /* ancillary_page_id */ + unsigned short ancillary_id[MAX_LANGUAGE_PER_DESC]; }; - /** * @param composition_id composition-page_id found in Subtitle descriptors * associated with subtitle stream in the PMT @@ -47,7 +47,7 @@ struct dvb_config * @return DVB context kept as void* for abstraction * */ -void* dvbsub_init_decoder(int composition_id,int ancillary_id); +void* dvbsub_init_decoder(int composition_id, int ancillary_id); int dvbsub_close_decoder(void *dvb_ctx); @@ -61,9 +61,8 @@ int dvbsub_close_decoder(void *dvb_ctx); * * @return -1 on error */ -int dvbsub_decode(void *dvb_ctx, - void *data, int *data_size, - const unsigned char *buf,int buf_size); +int dvbsub_decode(void *dvb_ctx, void *data, int *data_size, + const unsigned char *buf, int buf_size); /** * @func parse_dvb_description * @@ -74,8 +73,19 @@ int dvbsub_decode(void *dvb_ctx, * @return return -1 if invalid data found other wise 0 if everything goes well * errno is set is to EINVAL if invalid data is found */ -int parse_dvb_description (struct dvb_config* cfg,unsigned char*data,unsigned int len); +int parse_dvb_description(struct dvb_config* cfg, unsigned char*data, + unsigned int len); +/* + * @func dvbsub_set_write the output structure in dvb + * set ccx_s_write structure in dvb_ctx + * + * @param dvb_ctx context of dvb which was returned by dvbsub_init_decoder + * + * @param out output context returned by init_write + * + */ +void dvbsub_set_write(void *dvb_ctx, struct ccx_s_write *out); #ifdef __cplusplus } #endif diff --git a/src/spupng_encoder.c b/src/spupng_encoder.c index bf30cf85..7b68a073 100644 --- a/src/spupng_encoder.c +++ b/src/spupng_encoder.c @@ -292,3 +292,38 @@ void draw_char_indexed(uint8_t * canvas, int rowstride, uint8_t * pen, unicode_ccfont2(unicode, italic), underline * (3 << 24) /* cell row 24, 25 */); } + +void write_sputag(struct spupng_t *sp,LLONG ms_start,LLONG ms_end) +{ + fprintf(sp->fpxml, "fpxml, " end=\"%.3f\"", ((double)ms_end) / 1000); + fprintf(sp->fpxml, " image=\"%s\"", sp->pngfile); + fprintf(sp->fpxml, " xoffset=\"%d\"", sp->xOffset); + fprintf(sp->fpxml, " yoffset=\"%d\"", sp->yOffset); + fprintf(sp->fpxml, ">\n"); + fprintf(sp->fpxml, "\n"); + +} +void write_spucomment(struct spupng_t *sp,const char *str) +{ + fprintf(sp->fpxml, "\n"); +} + +int get_spupng_subtype(void) +{ + return (1 << CCX_OF_TYPE_TEXT)|(1<pngfile, "%s/sub%04d.png", sp->dirname, sp->fileIndex); + return sp->pngfile; +} +void inc_spupng_fileindex(void *ctx) +{ + struct spupng_t *sp = (struct spupng_t *)ctx; + sp->fileIndex++; +} + diff --git a/src/spupng_encoder.h b/src/spupng_encoder.h index 29ba7fa4..13576089 100644 --- a/src/spupng_encoder.h +++ b/src/spupng_encoder.h @@ -27,4 +27,8 @@ void write_spumux_header(struct ccx_s_write *out); void write_spumux_footer(struct ccx_s_write *out); void draw_char_indexed(uint8_t * canvas, int rowstride, uint8_t * pen, int unicode, int italic, int underline); +void write_sputag(struct spupng_t *sp,LLONG ms_start,LLONG ms_end); +void write_spucomment(struct spupng_t *sp,const char *str); +char* get_spupng_filename(void *ctx); +void inc_spupng_fileindex(void *ctx); #endif diff --git a/src/stream_functions.c b/src/stream_functions.c index 267a5535..b25cb1c9 100644 --- a/src/stream_functions.c +++ b/src/stream_functions.c @@ -171,6 +171,40 @@ int detect_myth( void ) return 0; } +int read_pts_pes(unsigned char*header, int len) +{ + unsigned int peslen = 0; + LLONG bits_9; + unsigned int bits_10; + unsigned int bits_11; + unsigned int bits_12; + unsigned int bits_13; + + //function used only to set start time + if(pts_set) + return -1; + //it might not be pes packet + if (!(header[0] == 0 && header[1] == 0 && header[2] == 1)) + return -1; + + + peslen = header[4] << 8 | header[5]; + + if (header[7] & 0x80) + { + bits_9 = ((LLONG) header[9] & 0x0E) << 29; // PTS 32..30 - Must be LLONG to prevent overflow + bits_10 = header[10] << 22; // PTS 29..22 + bits_11 = (header[11] & 0xFE) << 14; // PTS 21..15 + bits_12 = header[12] << 7; // PTS 14-7 + bits_13 = header[13] >> 1; // PTS 6-0 + } + else + return -1; + current_pts = bits_9 | bits_10 | bits_11 | bits_12 | bits_13; + pts_set = 1; + + return 0; +} /* Read and evaluate the current video PES header. The function returns * the length of the payload if successful, otherwise -1 is returned diff --git a/src/ts_functions.c b/src/ts_functions.c index c642d051..6cb715c0 100644 --- a/src/ts_functions.c +++ b/src/ts_functions.c @@ -366,6 +366,15 @@ long ts_readstream(void) haup_capbuflen = haup_newcapbuflen; } + /* + * if dvb subtitle is selected then start time taken from first PTS + * of any stream + */ + if ( cap_stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2 && cxx_dvb_context && !pts_set) + { + if(read_pts_pes(payload.start,payload.length) == 0) + set_fts(); + } // Check for PID with captions. Note that in Hauppauge mode we also process the video stream because // we need the timing from its PES header, which isn't included in Hauppauge's packets diff --git a/src/ts_tables.c b/src/ts_tables.c index 9ccfe863..bb65daab 100644 --- a/src/ts_tables.c +++ b/src/ts_tables.c @@ -210,13 +210,21 @@ int parse_PMT (int pos) ccx_options.ts_cappid = newcappid = elementary_PID; cap_stream_type=CCX_STREAM_TYPE_UNKNOWNSTREAM; } - if(IS_FEASIBLE(ccx_options.codec,ccx_options.nocodec,CCX_CODEC_DVB) && !ccx_options.ts_cappid && ccx_stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2) + if(IS_FEASIBLE(ccx_options.codec,ccx_options.nocodec,CCX_CODEC_DVB) && + !ccx_options.ts_cappid && + ccx_stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2 && + ES_info_length ) { unsigned char *es_info = payload_start + i + 5; for (desc_len = 0;(payload_start + i + 5 + ES_info_length) - es_info ;es_info += desc_len) { enum ccx_mpeg_descriptor descriptor_tag = (enum ccx_mpeg_descriptor)(*es_info++); desc_len = (*es_info++); + if(ccx_options.write_format != CCX_OF_SPUPNG ) + { + mprint ("DVB subtitle only support spupng type as output\n"); + continue; + } if(CCX_MPEG_DSC_DVB_SUBTITLE == descriptor_tag) { struct dvb_config cnf; @@ -227,6 +235,7 @@ int parse_PMT (int pos) cxx_dvb_context = dvbsub_init_decoder(cnf.composition_id[0],cnf.ancillary_id[0]); if (cxx_dvb_context == NULL) break; + dvbsub_set_write(cxx_dvb_context,&wbout1); ccx_options.ts_cappid = newcappid = elementary_PID; cap_stream_type = newcap_stream_type = ccx_stream_type; }