mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2024-12-25 04:11:38 +00:00
Implementation of DVB Subtitle
This commit is contained in:
parent
6033e5bea8
commit
a6c36197ba
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
#Ignore CVS
|
||||
.CVS
|
||||
CVS
|
||||
*.o
|
||||
linux/ccextractor
|
||||
linux/depend
|
||||
|
@ -19,7 +19,7 @@ src_OBJS = \
|
||||
encoding.o es_functions.o es_userdata.o file_functions.o \
|
||||
general_loop.o mp4.o myth.o output.o params_dump.o params.o \
|
||||
sequencing.o stream_functions.o telxcc.o timing.o ts_functions.o \
|
||||
utility.o wtv_functions.o xds.o
|
||||
utility.o wtv_functions.o xds.o dvb_subtitle_decoder.o ts_tables.o
|
||||
|
||||
gpacmp4_OBJS = \
|
||||
avc_ext.o avilib.o av_parsers.o base_encoding.o bitstream.o \
|
||||
@ -42,7 +42,8 @@ src_SRC = \
|
||||
../src/output.cpp ../src/params.cpp ../src/params_dump.cpp \
|
||||
../src/sequencing.cpp ../src/stream_functions.cpp ../src/telxcc.cpp \
|
||||
../src/timing.cpp ../src/ts_functions.cpp ../src/utility.cpp \
|
||||
../src/wtv_functions.cpp ../src/xds.cpp
|
||||
../src/wtv_functions.cpp ../src/xds.cpp ../src/dvb_subtitle_decoder.c \
|
||||
../src/ts_tables.cpp
|
||||
|
||||
gpacmp4_SRC = \
|
||||
../src/gpacmp4/avc_ext.c ../src/gpacmp4/avilib.c \
|
||||
|
@ -104,6 +104,11 @@ void init_options (struct ccx_s_options *options)
|
||||
options->direct_rollup=0; // Write roll-up captions directly instead of line by line?
|
||||
options->nofontcolor=0; // 1 = don't put <font color> tags
|
||||
options->notypesetting=0; // 1 = Don't put <i>, <u>, etc typesetting tags
|
||||
|
||||
/* Select subtitle codec */
|
||||
options->codec = CCX_CODEC_ANY;
|
||||
options->nocodec = CCX_CODEC_NONE;
|
||||
|
||||
/* Credit stuff */
|
||||
options->start_credits_text=NULL;
|
||||
options->end_credits_text=NULL;
|
||||
|
@ -42,6 +42,10 @@ struct ccx_s_options // Options from user parameters
|
||||
int nofontcolor;
|
||||
int notypesetting;
|
||||
struct ccx_boundary_time extraction_start, extraction_end; // Segment we actually process
|
||||
|
||||
/* subtitle codec type */
|
||||
enum cxx_code_type codec;
|
||||
enum cxx_code_type nocodec;
|
||||
/* Credit stuff */
|
||||
char *start_credits_text;
|
||||
char *end_credits_text;
|
||||
|
@ -123,6 +123,7 @@ enum ccx_mpeg_descriptor
|
||||
CCX_MPEG_DSC_VBI_DATA_DESCRIPTOR = 0x45,
|
||||
CCX_MPEG_DSC_VBI_TELETEXT_DESCRIPTOR = 0x46,
|
||||
CCX_MPEG_DSC_TELETEXT_DESCRIPTOR = 0x56,
|
||||
CCX_MPEG_DSC_DVB_SUBTITLE = 0x59,
|
||||
};
|
||||
|
||||
enum
|
||||
@ -191,7 +192,8 @@ enum ccx_bufferdata_type
|
||||
CCX_H264 = 3,
|
||||
CCX_HAUPPAGE = 4,
|
||||
CCX_TELETEXT = 5,
|
||||
CCX_PRIVATE_MPEG2_CC = 6
|
||||
CCX_PRIVATE_MPEG2_CC = 6,
|
||||
CCX_DVB_SUBTITLE = 7,
|
||||
};
|
||||
|
||||
enum ccx_frame_type
|
||||
@ -209,6 +211,32 @@ typedef enum {
|
||||
UNDEF = 0xff
|
||||
} bool_t;
|
||||
|
||||
enum cxx_code_type
|
||||
{
|
||||
CCX_CODEC_ANY,
|
||||
CCX_CODEC_TELETEXT,
|
||||
CCX_CODEC_DVB,
|
||||
CCX_CODEC_NONE,
|
||||
};
|
||||
|
||||
/*
|
||||
* This macro to be used when you want to find out whether you
|
||||
* should parse f_sel subtitle codec type or not
|
||||
*
|
||||
* @param u_sel pass the codec selected by user to be searched in
|
||||
* all elementry stream, we ignore the not to be selected stream
|
||||
* if we find stream this is selected stream. since setting
|
||||
* selected stream and not selected to same codec does not
|
||||
* make ay sense.
|
||||
*
|
||||
* @param u_nsel pass the codec selected by user not to be parsed
|
||||
* we give false value if f_sel is equal to n_sel
|
||||
* and vice versa true if ...
|
||||
*
|
||||
* @param f_sel pass the codec name whom you are tesing to be feasible
|
||||
* to parse.
|
||||
*/
|
||||
#define IS_FEASIBLE(u_sel,u_nsel,f_sel) ( ( (u_sel) == CCX_CODEC_ANY && (u_nsel) != (f_sel) ) || (u_sel) == (f_sel) )
|
||||
#define CCX_TXT_FORBIDDEN 0 // Ignore teletext packets
|
||||
#define CCX_TXT_AUTO_NOT_YET_FOUND 1
|
||||
#define CCX_TXT_IN_USE 2 // Positive autodetected, or forced, etc
|
||||
|
1643
src/dvb_subtitle_decoder.c
Normal file
1643
src/dvb_subtitle_decoder.c
Normal file
File diff suppressed because it is too large
Load Diff
74
src/dvb_subtitle_decoder.h
Normal file
74
src/dvb_subtitle_decoder.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* DVB subtitle decoding
|
||||
* Copyright (c) 2014 Anshul
|
||||
* License: LGPL
|
||||
*
|
||||
* This file is part of CCEXtractor
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with CCExtractor; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @file dvbsub.c
|
||||
*/
|
||||
|
||||
#ifndef DVBSUBDEC_H
|
||||
#define DVBSUBDEC_H
|
||||
|
||||
#define MAX_LANGUAGE_PER_DESC 5
|
||||
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param composition_id composition-page_id found in Subtitle descriptors
|
||||
* associated with subtitle stream in the PMT
|
||||
* it could be -1 if not found in PMT.
|
||||
* @param ancillary_id ancillary-page_id found in Subtitle descriptors
|
||||
* associated with subtitle stream in the PMT.
|
||||
* it could be -1 if not found in PMT.
|
||||
*
|
||||
* @return DVB context kept as void* for abstraction
|
||||
*
|
||||
*/
|
||||
void* dvbsub_init_decoder(int composition_id,int ancillary_id);
|
||||
|
||||
int dvbsub_close_decoder(void *dvb_ctx);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* 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);
|
||||
/**
|
||||
* @func parse_dvb_description
|
||||
*
|
||||
* data pointer to this function should be after description length and description tag is parsed
|
||||
*
|
||||
* @param cfg preallocated dvb_config structure where parsed description will be stored,Not to be NULL
|
||||
*
|
||||
* @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);
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
#endif
|
||||
|
||||
#include "708.h"
|
||||
#include "dvb_subtitle_decoder.h"
|
||||
|
||||
// IMPORTED TRASH INFO, REMOVE
|
||||
extern long num_nal_unit_type_7;
|
||||
@ -43,10 +44,10 @@ unsigned char *filebuffer;
|
||||
LLONG filebuffer_start; // Position of buffer start relative to file
|
||||
int filebuffer_pos; // Position of pointer relative to buffer start
|
||||
int bytesinbuffer; // Number of bytes we actually have on buffer
|
||||
extern void *cxx_dvb_context;
|
||||
|
||||
LLONG process_raw_with_field (void);
|
||||
|
||||
|
||||
// Program stream specific data grabber
|
||||
LLONG ps_getmoredata(void)
|
||||
{
|
||||
@ -598,6 +599,12 @@ void general_loop(void)
|
||||
if (pts_set)
|
||||
set_fts(); // Try to fix timing from TS data
|
||||
}
|
||||
else if(ccx_bufferdatatype == CCX_DVB_SUBTITLE)
|
||||
{
|
||||
int out_size = 0;
|
||||
dvbsub_decode(cxx_dvb_context,NULL,&out_size,buffer + 2,inbuf);
|
||||
got = inbuf;
|
||||
}
|
||||
else if (ccx_bufferdatatype == CCX_PES)
|
||||
{
|
||||
got = process_m2v (buffer, inbuf);
|
||||
|
@ -560,6 +560,7 @@ void usage (void)
|
||||
mprint ("generate a .srt file, with only data from 3:00 to 5:00 in the input file(s)\n");
|
||||
mprint ("and then add that (huge) delay, which would make the final file start at\n");
|
||||
mprint ("5:00 and end at 7:00.\n\n");
|
||||
|
||||
mprint ("Options that affect what segment of the input file(s) to process:\n");
|
||||
mprint (" -startat time: Only write caption information that starts after the\n");
|
||||
mprint (" given time.\n");
|
||||
@ -572,6 +573,24 @@ void usage (void)
|
||||
mprint (" output formats. In all formats with timing information\n");
|
||||
mprint (" the times are unchanged.\n");
|
||||
mprint ("-scr --screenfuls num: Write 'num' screenfuls and terminate processing.\n\n");
|
||||
|
||||
mprint ("Options that affect which codec is to be used have to be searched in input\n");
|
||||
mprint (" If codec type is not selected then first elementry stream suitable for \n"
|
||||
" subtitle is selected, please consider -teletext -noteletext override this\n"
|
||||
" option.\n"
|
||||
" -cocdec dvbsub select the dvb subtitle from all elementry stream,\n"
|
||||
" if stream of dvb subtitle type is not found then \n"
|
||||
" nothing is selected and no subtitle is generated\n"
|
||||
" -nocodec dvbsub ignore dvb subtitle and follow default behaviour\n"
|
||||
" -codec teletext select the teletext subtitle from elementry stream\n"
|
||||
" -nocodec teletext ignore teletext subtitle\n"
|
||||
" NOTE: option given in form -foo=bar ,-foo = bar and --foo=bar are invalid\n"
|
||||
" valid option are only in form -foo bar\n"
|
||||
" nocodec and codec parameter must not be same if found to be same \n"
|
||||
" then parameter of nocodec is ignored, this flag should be passed \n"
|
||||
" once more then one are not supported yet and last parameter would \n"
|
||||
" taken in consideration\n");
|
||||
|
||||
mprint ("Adding start and end credits:\n");
|
||||
mprint (" CCExtractor can _try_ to add a custom message (for credits for example) at\n");
|
||||
mprint (" the start and end of the file, looking for a window where there are no\n");
|
||||
@ -818,6 +837,45 @@ void parse_parameters (int argc, char *argv[])
|
||||
set_input_format (argv[i]+4);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*user specified subtitle to be selected */
|
||||
|
||||
if(!strcmp (argv[i],"-codec"))
|
||||
{
|
||||
i++;
|
||||
if(!strcmp (argv[i],"teletext"))
|
||||
{
|
||||
ccx_options.codec = CCX_CODEC_TELETEXT;
|
||||
}
|
||||
else if(!strcmp (argv[i],"dvbsub"))
|
||||
{
|
||||
ccx_options.codec = CCX_CODEC_DVB;
|
||||
}
|
||||
else
|
||||
{
|
||||
mprint("Invalid option for codec %s\n",argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/*user specified subtitle to be selected */
|
||||
|
||||
if(!strcmp (argv[i],"-nocodec"))
|
||||
{
|
||||
i++;
|
||||
if(!strcmp (argv[i],"teletext"))
|
||||
{
|
||||
ccx_options.nocodec = CCX_CODEC_TELETEXT;
|
||||
}
|
||||
else if(!strcmp (argv[i],"dvbsub"))
|
||||
{
|
||||
ccx_options.nocodec = CCX_CODEC_DVB;
|
||||
}
|
||||
else
|
||||
{
|
||||
mprint("Invalid option for codec %s\n",argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* Output file formats */
|
||||
if (strcmp (argv[i],"-srt")==0 ||
|
||||
strcmp (argv[i],"-dvdraw")==0 ||
|
||||
@ -1367,11 +1425,13 @@ void parse_parameters (int argc, char *argv[])
|
||||
}
|
||||
if (strcmp (argv[i],"-teletext")==0)
|
||||
{
|
||||
ccx_options.codec = CCX_CODEC_TELETEXT;
|
||||
ccx_options.teletext_mode=CCX_TXT_IN_USE;
|
||||
continue;
|
||||
}
|
||||
if (strcmp (argv[i],"-noteletext")==0)
|
||||
{
|
||||
ccx_options.nocodec = CCX_CODEC_TELETEXT;
|
||||
ccx_options.teletext_mode=CCX_TXT_FORBIDDEN;
|
||||
continue;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ static long haup_capbuflen = 0; // Bytes read in haup_capbuf
|
||||
unsigned TS_program_number = 0; // Identifier for current program
|
||||
unsigned pmtpid = 0; // PID for Program Map Table
|
||||
unsigned cap_stream_type=CCX_STREAM_TYPE_UNKNOWNSTREAM; // Stream type for cappid
|
||||
|
||||
extern void *cxx_dvb_context;
|
||||
|
||||
// Descriptions for ts ccx_stream_type
|
||||
const char *desc[256];
|
||||
@ -463,6 +463,11 @@ LLONG ts_getmoredata(void)
|
||||
{
|
||||
ccx_bufferdatatype = CCX_H264;
|
||||
tstr = "H.264";
|
||||
}
|
||||
else if ( cap_stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2 && cxx_dvb_context )
|
||||
{
|
||||
ccx_bufferdatatype = CCX_DVB_SUBTITLE;
|
||||
tstr = "DVB subtitle";
|
||||
}
|
||||
else if ( cap_stream_type == CCX_STREAM_TYPE_UNKNOWNSTREAM && ccx_options.hauppauge_mode)
|
||||
{
|
||||
@ -566,13 +571,6 @@ LLONG ts_getmoredata(void)
|
||||
haup_capbuflen=0;
|
||||
}
|
||||
|
||||
if( !((stream_id&0xf0)==0xe0)) // 0xBD = private stream
|
||||
{
|
||||
// ??? Shouldn't happen. Complain and try again.
|
||||
mprint("Not a video PES header!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
dbg_print(CCX_DMT_VERBOSE, "TS payload start video PES id: %d len: %ld\n",
|
||||
stream_id, capbuflen);
|
||||
|
||||
|
@ -6,8 +6,10 @@
|
||||
*/
|
||||
|
||||
#include "ccextractor.h"
|
||||
#include "dvb_subtitle_decoder.h"
|
||||
|
||||
static unsigned pmt_warning_shown=0; // Only display warning once
|
||||
void *cxx_dvb_context = NULL;
|
||||
|
||||
// PMTs table
|
||||
PAT_entry pmt_array[TS_PMT_MAP_SIZE] = { 0 };
|
||||
@ -64,6 +66,8 @@ void clear_PMT_array (void)
|
||||
int parse_PMT (int pos)
|
||||
{
|
||||
int must_flush=0;
|
||||
int ret = 0;
|
||||
unsigned char desc_len = 0;
|
||||
|
||||
if ((ccx_options.ts_forced_cappid || (ccx_options.teletext_mode==CCX_TXT_IN_USE && ccx_options.ts_cappid)) &&
|
||||
cap_stream_type!=CCX_STREAM_TYPE_UNKNOWNSTREAM) // Already know what we need, skip
|
||||
@ -196,14 +200,41 @@ int parse_PMT (int pos)
|
||||
unsigned ES_info_length = (((payload_start[i+3] & 0x0F) << 8)
|
||||
| payload_start[i+4]);
|
||||
|
||||
/* There is no information about elementry stream */
|
||||
if(!ES_info_length)
|
||||
continue;
|
||||
|
||||
if (ccx_options.ts_cappid==0 && ccx_stream_type==ccx_options.ts_datastreamtype) // Found a stream with the type the user wants
|
||||
{
|
||||
ccx_options.ts_forced_cappid=1;
|
||||
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)
|
||||
{
|
||||
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_MPEG_DSC_DVB_SUBTITLE == descriptor_tag)
|
||||
{
|
||||
struct dvb_config cnf;
|
||||
memset((void*)&cnf,0,sizeof(struct dvb_config));
|
||||
ret = parse_dvb_description(&cnf,es_info,desc_len);
|
||||
if(ret < 0)
|
||||
break;
|
||||
cxx_dvb_context = dvbsub_init_decoder(cnf.composition_id[0],cnf.ancillary_id[0]);
|
||||
if (cxx_dvb_context == NULL)
|
||||
break;
|
||||
ccx_options.ts_cappid = newcappid = elementary_PID;
|
||||
cap_stream_type = newcap_stream_type = ccx_stream_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ccx_options.teletext_mode==CCX_TXT_AUTO_NOT_YET_FOUND ||
|
||||
|
||||
if (IS_FEASIBLE(ccx_options.codec,ccx_options.nocodec,CCX_CODEC_TELETEXT) && (ccx_options.teletext_mode==CCX_TXT_AUTO_NOT_YET_FOUND ||
|
||||
(ccx_options.teletext_mode==CCX_TXT_IN_USE && !ccx_options.ts_cappid)) // Want teletext but don't know the PID yet
|
||||
&& ccx_stream_type == CCX_STREAM_TYPE_PRIVATE_MPEG2) // MPEG-2 Packetized Elementary Stream packets containing private data
|
||||
{
|
||||
@ -551,6 +582,10 @@ void process_ccx_mpeg_descriptor (unsigned char *data, unsigned length)
|
||||
dbg_print (CCX_DMT_PMT, " Initial page: %02X\n",teletext_page_number);
|
||||
}
|
||||
break;
|
||||
case CCX_MPEG_DSC_DVB_SUBTITLE:
|
||||
dbg_print(CCX_DMT_PMT, " DVB Subtitle descriptor\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (data[0]==CCX_MPEG_DSC_REGISTRATION) // Registration descriptor, could be useful eventually
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user