mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2024-12-25 04:11:38 +00:00
Merge branch 'master' of https://github.com/CCExtractor/ccextractor
This commit is contained in:
commit
560a88b0b9
@ -243,7 +243,14 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "MP4 requires an actual file, it's not possible to read from a stream, including stdin.\n");
|
||||
}
|
||||
tmp = processmp4(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
|
||||
if(ccx_options.extract_chapters)
|
||||
{
|
||||
tmp = dumpchapters(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = processmp4(ctx, &ctx->mp4_cfg, ctx->inputfile[ctx->current_file]);
|
||||
}
|
||||
if (ccx_options.print_file_reports)
|
||||
print_file_report(ctx);
|
||||
if (!ret) ret = tmp;
|
||||
|
@ -190,6 +190,39 @@ static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_I
|
||||
return status;
|
||||
}
|
||||
|
||||
static char *format_duration(u64 dur, u32 timescale, char *szDur)
|
||||
{
|
||||
u32 h, m, s, ms;
|
||||
if ((dur==(u64) -1) || (dur==(u32) -1)) {
|
||||
strcpy(szDur, "Unknown");
|
||||
return szDur;
|
||||
}
|
||||
dur = (u64) (( ((Double) (s64) dur)/timescale)*1000);
|
||||
h = (u32) (dur / 3600000);
|
||||
m = (u32) (dur/ 60000) - h*60;
|
||||
s = (u32) (dur/1000) - h*3600 - m*60;
|
||||
ms = (u32) (dur) - h*3600000 - m*60000 - s*1000;
|
||||
if (h<=24) {
|
||||
sprintf(szDur, "%02d:%02d:%02d.%03d", h, m, s, ms);
|
||||
} else {
|
||||
u32 d = (u32) (dur / 3600000 / 24);
|
||||
h = (u32) (dur/3600000)-24*d;
|
||||
if (d<=365) {
|
||||
sprintf(szDur, "%d Days, %02d:%02d:%02d.%03d", d, h, m, s, ms);
|
||||
} else {
|
||||
u32 y=0;
|
||||
while (d>365) {
|
||||
y++;
|
||||
d-=365;
|
||||
if (y%4) d--;
|
||||
}
|
||||
sprintf(szDur, "%d Years %d Days, %02d:%02d:%02d.%03d", y, d, h, m, s, ms);
|
||||
}
|
||||
|
||||
}
|
||||
return szDur;
|
||||
}
|
||||
|
||||
unsigned char * ccdp_find_data(unsigned char * ccdp_atom_content, unsigned int len, unsigned int *cc_count)
|
||||
{
|
||||
unsigned char *data = ccdp_atom_content;
|
||||
@ -286,7 +319,7 @@ unsigned char * ccdp_find_data(unsigned char * ccdp_atom_content, unsigned int l
|
||||
*/
|
||||
int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
{
|
||||
int caps = 0;
|
||||
int mp4_ret = 0;
|
||||
GF_ISOFile* f;
|
||||
u32 i, j, track_count, avc_track_count, cc_track_count;
|
||||
struct cc_subtitle dec_sub;
|
||||
@ -296,7 +329,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
dec_ctx = update_decoder_list(ctx);
|
||||
|
||||
memset(&dec_sub,0,sizeof(dec_sub));
|
||||
mprint("opening \'%s\': ", file);
|
||||
mprint("Opening \'%s\': ", file);
|
||||
#ifdef MP4_DEBUG
|
||||
gf_log_set_tool_level(GF_LOG_CONTAINER,GF_LOG_DEBUG);
|
||||
#endif
|
||||
@ -330,7 +363,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
avc_track_count++;
|
||||
}
|
||||
|
||||
mprint("mp4: found %u tracks: %u avc and %u cc\n", track_count, avc_track_count, cc_track_count);
|
||||
mprint("MP4: found %u tracks: %u avc and %u cc\n", track_count, avc_track_count, cc_track_count);
|
||||
|
||||
for(i = 0; i < track_count; i++)
|
||||
{
|
||||
@ -349,7 +382,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
}
|
||||
if(dec_sub.got_output)
|
||||
{
|
||||
caps = 1;
|
||||
mp4_ret = 1;
|
||||
encode_sub(enc_ctx, &dec_sub);
|
||||
dec_sub.got_output = 0;
|
||||
}
|
||||
@ -377,7 +410,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
}
|
||||
if(dec_sub.got_output)
|
||||
{
|
||||
caps = 1;
|
||||
mp4_ret = 1;
|
||||
encode_sub(enc_ctx, &dec_sub);
|
||||
dec_sub.got_output = 0;
|
||||
}
|
||||
@ -472,14 +505,14 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
|
||||
if (cc_info == CDP_SECTION_SVC_INFO || cc_info == CDP_SECTION_FOOTER)
|
||||
{
|
||||
dbg_print(CCX_DMT_PARSE, "mp4-708: premature end of sample (0x73 or 0x74)\n");
|
||||
dbg_print(CCX_DMT_PARSE, "MP4-708: premature end of sample (0x73 or 0x74)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((cc_info == 0xFA || cc_info == 0xFC || cc_info == 0xFD)
|
||||
&& (cc_data[1] & 0x7F) == 0 && (cc_data[2] & 0x7F) == 0)
|
||||
{
|
||||
dbg_print(CCX_DMT_PARSE, "mp4-708: skipped (zero cc data)\n");
|
||||
dbg_print(CCX_DMT_PARSE, "MP4-708: skipped (zero cc data)\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -490,7 +523,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
|
||||
if (cc_type < 2)
|
||||
{
|
||||
dbg_print(CCX_DMT_PARSE, "mp4-708: atom skipped (cc_type < 2)\n");
|
||||
dbg_print(CCX_DMT_PARSE, "MP4-708: atom skipped (cc_type < 2)\n");
|
||||
continue;
|
||||
}
|
||||
dec_ctx->dtvcc->encoder = (void *)enc_ctx; //WARN: otherwise cea-708 will not work
|
||||
@ -522,7 +555,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
tdata += ret;
|
||||
cb_field1++;
|
||||
if (dec_sub.got_output) {
|
||||
caps = 1;
|
||||
mp4_ret = 1;
|
||||
encode_sub(enc_ctx, &dec_sub);
|
||||
dec_sub.got_output = 0;
|
||||
}
|
||||
@ -550,7 +583,7 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
|
||||
free(dec_ctx->xds_ctx);
|
||||
|
||||
mprint("\nclosing media: ");
|
||||
mprint("\nClosing media: ");
|
||||
|
||||
gf_isom_close(f);
|
||||
f = NULL;
|
||||
@ -567,9 +600,66 @@ int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
if (cc_track_count)
|
||||
mprint ("Found %d CC track(s).\n", cc_track_count);
|
||||
else
|
||||
mprint ("found no dedicated CC track(s).\n");
|
||||
mprint ("Found no dedicated CC track(s).\n");
|
||||
|
||||
ctx->freport.mp4_cc_track_cnt = cc_track_count;
|
||||
|
||||
return caps;
|
||||
return mp4_ret;
|
||||
}
|
||||
|
||||
int dumpchapters (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file)
|
||||
{
|
||||
int mp4_ret = 0;
|
||||
GF_ISOFile* f;
|
||||
mprint("Opening \'%s\': ", file);
|
||||
#ifdef MP4_DEBUG
|
||||
gf_log_set_tool_level(GF_LOG_CONTAINER,GF_LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
if((f = gf_isom_open(file, GF_ISOM_OPEN_READ, NULL)) == NULL)
|
||||
{
|
||||
mprint("failed to open\n");
|
||||
return 5;
|
||||
}
|
||||
|
||||
mprint("ok\n");
|
||||
|
||||
char szName[1024];
|
||||
FILE *t;
|
||||
u32 i, count;
|
||||
count = gf_isom_get_chapter_count(f, 0);
|
||||
if(count>0)
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
strcpy(szName, get_basename(file));
|
||||
strcat(szName, ".txt");
|
||||
|
||||
t = gf_fopen(szName, "wt");
|
||||
if (!t) return 5;
|
||||
}
|
||||
else {
|
||||
t = stdout;
|
||||
}
|
||||
mp4_ret=1;
|
||||
printf("Writing chapters into %s\n",szName);
|
||||
}
|
||||
else
|
||||
{
|
||||
mprint("No chapters information found!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
u64 chapter_time;
|
||||
const char *name;
|
||||
char szDur[20];
|
||||
gf_isom_get_chapter(f, 0, i+1, &chapter_time, &name);
|
||||
fprintf(t, "CHAPTER%02d=%s\n", i+1, format_duration(chapter_time, 1000, szDur));
|
||||
fprintf(t, "CHAPTER%02dNAME=%s\n", i+1, name);
|
||||
|
||||
}
|
||||
if (file) gf_fclose(t);
|
||||
return mp4_ret;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ void init_options (struct ccx_s_options *options)
|
||||
options->auto_myth = 2; // 2=auto
|
||||
/* MP4 related stuff */
|
||||
options->mp4vidtrack=0; // Process the video track even if a CC dedicated track exists.
|
||||
options->extract_chapters=0; // By default don't extract chapters.
|
||||
/* General stuff */
|
||||
options->usepicorder = 0; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
|
||||
options->xmltv=0; // 1 = full output. 2 = live output. 3 = both
|
||||
|
@ -115,6 +115,7 @@ struct ccx_s_options // Options from user parameters
|
||||
int auto_myth; // Use myth-tv mpeg code? 0=no, 1=yes, 2=auto
|
||||
/* MP4 related stuff */
|
||||
unsigned mp4vidtrack; // Process the video track even if a CC dedicated track exists.
|
||||
int extract_chapters; // If 1, extracts chapters (if present), from MP4 files.
|
||||
/* General settings */
|
||||
int usepicorder; // Force the use of pic_order_cnt_lsb in AVC/H.264 data streams
|
||||
int xmltv; // 1 = full output. 2 = live output. 3 = both
|
||||
|
@ -279,7 +279,7 @@ void ccx_dtvcc_write_transcript(ccx_dtvcc_writer_ctx *writer, ccx_dtvcc_service_
|
||||
if (strlen(buf))
|
||||
write(encoder->dtvcc_writers[tv->service_number - 1].fd, buf, strlen(buf));
|
||||
|
||||
_dtvcc_write_row(writer, tv, i, encoder, 0);
|
||||
_dtvcc_write_row(writer, decoder, i, encoder, 0);
|
||||
write(encoder->dtvcc_writers[tv->service_number - 1].fd,
|
||||
encoder->encoded_crlf, encoder->encoded_crlf_length);
|
||||
}
|
||||
|
@ -4,4 +4,5 @@
|
||||
|
||||
|
||||
int processmp4 (struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file);
|
||||
int dumpchapters(struct lib_ccx_ctx *ctx,struct ccx_s_mp4Cfg *cfg, char *file);
|
||||
#endif
|
||||
|
@ -490,6 +490,9 @@ void print_usage (void)
|
||||
mprint (" --webvtt-create-css: Create a separate file for CSS instead of inline.\n");
|
||||
mprint ("\n");
|
||||
mprint ("Options that affect what kind of output will be produced:\n");
|
||||
mprint (" -chapters: (Experimental) Produces a chapter file from MP4 files.\n");
|
||||
mprint (" Note that this must only be used with MP4 files,\n");
|
||||
mprint (" for other files it will simply generate subtitles file.\n");
|
||||
mprint (" -bom: Append a BOM (Byte Order Mark) to output files.\n");
|
||||
mprint (" Note that most text processing tools in linux will not\n");
|
||||
mprint (" like BOM.\n");
|
||||
@ -1199,6 +1202,11 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(argv[i], "-chapters") == 0){
|
||||
opt->extract_chapters= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp (argv[i],"-bi")==0 ||
|
||||
strcmp (argv[i],"--bufferinput")==0)
|
||||
@ -2195,6 +2203,13 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
|
||||
{
|
||||
fatal (EXIT_INCOMPATIBLE_PARAMETERS, "MP4 requires an actual file, it's not possible to read from a stream, including stdin.\n");
|
||||
}
|
||||
|
||||
if(opt->extract_chapters)
|
||||
{
|
||||
mprint("Request to extract chapters recieved.\n");
|
||||
mprint("Note that this must only be used with MP4 files,\n");
|
||||
mprint("for other files it will simply generate subtitles file.\n\n");
|
||||
}
|
||||
|
||||
if(opt->gui_mode_reports)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user