⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvbsubdec.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * DVB subtitle decoding for ffmpeg * Copyright (c) 2005 Ian Caulfield. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "avcodec.h"#include "dsputil.h"#include "bitstream.h"//#define DEBUG//#define DEBUG_PACKET_CONTENTS//#define DEBUG_SAVE_IMAGES#define DVBSUB_PAGE_SEGMENT     0x10#define DVBSUB_REGION_SEGMENT   0x11#define DVBSUB_CLUT_SEGMENT     0x12#define DVBSUB_OBJECT_SEGMENT   0x13#define DVBSUB_DISPLAY_SEGMENT  0x80static unsigned char *cm;#ifdef DEBUG_SAVE_IMAGES#undef fprintf#if 0static void png_save(const char *filename, uint8_t *bitmap, int w, int h,                     uint32_t *rgba_palette){    int x, y, v;    FILE *f;    char fname[40], fname2[40];    char command[1024];    snprintf(fname, 40, "%s.ppm", filename);    f = fopen(fname, "w");    if (!f) {        perror(fname);        exit(1);    }    fprintf(f, "P6\n"            "%d %d\n"            "%d\n",            w, h, 255);    for(y = 0; y < h; y++) {        for(x = 0; x < w; x++) {            v = rgba_palette[bitmap[y * w + x]];            putc((v >> 16) & 0xff, f);            putc((v >> 8) & 0xff, f);            putc((v >> 0) & 0xff, f);        }    }    fclose(f);    snprintf(fname2, 40, "%s-a.pgm", filename);    f = fopen(fname2, "w");    if (!f) {        perror(fname2);        exit(1);    }    fprintf(f, "P5\n"            "%d %d\n"            "%d\n",            w, h, 255);    for(y = 0; y < h; y++) {        for(x = 0; x < w; x++) {            v = rgba_palette[bitmap[y * w + x]];            putc((v >> 24) & 0xff, f);        }    }    fclose(f);    snprintf(command, 1024, "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);    system(command);    snprintf(command, 1024, "rm %s %s", fname, fname2);    system(command);}#endifstatic void png_save2(const char *filename, uint32_t *bitmap, int w, int h){    int x, y, v;    FILE *f;    char fname[40], fname2[40];    char command[1024];    snprintf(fname, 40, "%s.ppm", filename);    f = fopen(fname, "w");    if (!f) {        perror(fname);        exit(1);    }    fprintf(f, "P6\n"            "%d %d\n"            "%d\n",            w, h, 255);    for(y = 0; y < h; y++) {        for(x = 0; x < w; x++) {            v = bitmap[y * w + x];            putc((v >> 16) & 0xff, f);            putc((v >> 8) & 0xff, f);            putc((v >> 0) & 0xff, f);        }    }    fclose(f);    snprintf(fname2, 40, "%s-a.pgm", filename);    f = fopen(fname2, "w");    if (!f) {        perror(fname2);        exit(1);    }    fprintf(f, "P5\n"            "%d %d\n"            "%d\n",            w, h, 255);    for(y = 0; y < h; y++) {        for(x = 0; x < w; x++) {            v = bitmap[y * w + x];            putc((v >> 24) & 0xff, f);        }    }    fclose(f);    snprintf(command, 1024, "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);    system(command);    snprintf(command, 1024, "rm %s %s", fname, fname2);    system(command);}#endif#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))typedef struct DVBSubCLUT {    int id;    uint32_t clut4[4];    uint32_t clut16[16];    uint32_t clut256[256];    struct DVBSubCLUT *next;} DVBSubCLUT;static DVBSubCLUT default_clut;typedef struct DVBSubObjectDisplay {    int object_id;    int region_id;    int x_pos;    int y_pos;    int fgcolour;    int bgcolour;    struct DVBSubObjectDisplay *region_list_next;    struct DVBSubObjectDisplay *object_list_next;} DVBSubObjectDisplay;typedef struct DVBSubObject {    int id;    int type;    DVBSubObjectDisplay *display_list;    struct DVBSubObject *next;} DVBSubObject;typedef struct DVBSubRegionDisplay {    int region_id;    int x_pos;    int y_pos;    struct DVBSubRegionDisplay *next;} DVBSubRegionDisplay;typedef struct DVBSubRegion {    int id;    int width;    int height;    int depth;    int clut;    int bgcolour;    uint8_t *pbuf;    int buf_size;    DVBSubObjectDisplay *display_list;    struct DVBSubRegion *next;} DVBSubRegion;typedef struct DVBSubContext {    int composition_id;    int ancillary_id;    int time_out;    DVBSubRegion *region_list;    DVBSubCLUT   *clut_list;    DVBSubObject *object_list;    int display_list_size;    DVBSubRegionDisplay *display_list;} DVBSubContext;static DVBSubObject* get_object(DVBSubContext *ctx, int object_id){    DVBSubObject *ptr = ctx->object_list;    while (ptr != NULL && ptr->id != object_id) {        ptr = ptr->next;    }    return ptr;}static DVBSubCLUT* get_clut(DVBSubContext *ctx, int clut_id){    DVBSubCLUT *ptr = ctx->clut_list;    while (ptr != NULL && ptr->id != clut_id) {        ptr = ptr->next;    }    return ptr;}static DVBSubRegion* get_region(DVBSubContext *ctx, int region_id){    DVBSubRegion *ptr = ctx->region_list;    while (ptr != NULL && ptr->id != region_id) {        ptr = ptr->next;    }    return ptr;}static void delete_region_display_list(DVBSubContext *ctx, DVBSubRegion *region){    DVBSubObject *object, *obj2, **obj2_ptr;    DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr;    while (region->display_list != NULL) {        display = region->display_list;        object = get_object(ctx, display->object_id);        if (object != NULL) {            obj_disp = object->display_list;            obj_disp_ptr = &object->display_list;            while (obj_disp != NULL && obj_disp != display) {                obj_disp_ptr = &obj_disp->object_list_next;                obj_disp = obj_disp->object_list_next;            }            if (obj_disp) {                *obj_disp_ptr = obj_disp->object_list_next;                if (object->display_list == NULL) {                    obj2 = ctx->object_list;                    obj2_ptr = &ctx->object_list;                    while (obj2 != NULL && obj2 != object) {                        obj2_ptr = &obj2->next;                        obj2 = obj2->next;                    }                    *obj2_ptr = obj2->next;                    av_free(obj2);                }            }        }        region->display_list = display->region_list_next;        av_free(display);    }}static void delete_state(DVBSubContext *ctx){    DVBSubRegion *region;    DVBSubCLUT *clut;    while (ctx->region_list != NULL)    {        region = ctx->region_list;        ctx->region_list = region->next;        delete_region_display_list(ctx, region);        if (region->pbuf != NULL)            av_free(region->pbuf);        av_free(region);    }    while (ctx->clut_list != NULL)    {        clut = ctx->clut_list;        ctx->clut_list = clut->next;        av_free(clut);    }    /* Should already be null */    if (ctx->object_list != NULL)        av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n");}static int dvbsub_init_decoder(AVCodecContext *avctx){    int i, r, g, b, a = 0;    DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;    cm = cropTbl + MAX_NEG_CROP;    memset(avctx->priv_data, 0, sizeof(DVBSubContext));    ctx->composition_id = avctx->sub_id & 0xffff;    ctx->ancillary_id = avctx->sub_id >> 16;    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.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);    }    return 0;}static int dvbsub_close_decoder(AVCodecContext *avctx){    DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;    DVBSubRegionDisplay *display;    delete_state(ctx);    while (ctx->display_list != NULL)    {        display = ctx->display_list;        ctx->display_list = display->next;        av_free(display);    }    return 0;}static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len,                                   uint8_t **srcbuf, int buf_size,                                   int non_mod, uint8_t *map_table){    GetBitContext gb;    int bits;    int run_length;    int pixels_read = 0;    init_get_bits(&gb, *srcbuf, buf_size << 8);    while (get_bits_count(&gb) < (buf_size << 8) && pixels_read < dbuf_len) {        bits = get_bits(&gb, 2);        if (bits != 0) {            if (non_mod != 1 || bits != 1) {                if (map_table != NULL)                    *destbuf++ = map_table[bits];                else                    *destbuf++ = bits;            }            pixels_read++;        } else {            bits = get_bits(&gb, 1);            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 != NULL)                        bits = map_table[bits];                    while (run_length-- > 0 && pixels_read < dbuf_len) {                        *destbuf++ = bits;                        pixels_read++;                    }                }            } else {                bits = get_bits(&gb, 1);                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 != NULL)                                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 != NULL)                                bits = map_table[bits];                            while (run_length-- > 0 && pixels_read < dbuf_len) {                                *destbuf++ = bits;                                pixels_read++;                            }                        }                    } else if (bits == 1) {                        pixels_read += 2;                        if (map_table != NULL)                            bits = map_table[0];                        else                            bits = 0;                        if (pixels_read <= dbuf_len) {                            *destbuf++ = bits;                            *destbuf++ = bits;                        }                    } else {                        (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;                        return pixels_read;                    }                } else {                    if (map_table != NULL)                        bits = map_table[0];                    else                        bits = 0;                    *destbuf++ = bits;                    pixels_read++;                }            }        }    }    if (get_bits(&gb, 6) != 0)        av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");    (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;    return pixels_read;}static int dvbsub_read_4bit_string(uint8_t *destbuf, int dbuf_len,                                   uint8_t **srcbuf, int buf_size,                                   int non_mod, uint8_t *map_table){    GetBitContext gb;    int bits;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -