This commit is contained in:
Carlos Fernandez 2017-01-23 12:34:06 -08:00
commit 560a88b0b9
7 changed files with 129 additions and 14 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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)
{