Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/gpacmp4/gpac/isomedia.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ enum
GF_ISOM_SUBTYPE_LSR1 = GF_4CC( 'l', 's', 'r', '1' ),

/* CAPTIONS */
GF_ISOM_SUBTYPE_C608 = GF_4CC ('c', '6', '0', '8' ),
GF_ISOM_SUBTYPE_C708 = GF_4CC('c', '7', '0', '8')
GF_ISOM_SUBTYPE_C608 = GF_4CC( 'c', '6', '0', '8' ),
GF_ISOM_SUBTYPE_C708 = GF_4CC( 'c', '7', '0', '8' )
};


Expand Down
12 changes: 7 additions & 5 deletions src/gpacmp4/isom_read.c
Original file line number Diff line number Diff line change
Expand Up @@ -1736,24 +1736,26 @@ GF_Err gf_isom_get_chunks_infos(GF_ISOFile *movie, u32 trackNumber, u32 *dur_min
chunk_dur += dur;
stbl_GetSampleSize(trak->Media->information->sampleTable->SampleSize, k+sample_idx, &size);
chunk_size += size;

}
if (dmin>chunk_dur) dmin = chunk_dur;
if (dmax<chunk_dur) dmax = chunk_dur;
davg += chunk_dur;
if (smin>chunk_size) smin = chunk_size;
if (smax<chunk_size) smax = chunk_size;
savg += chunk_dur;
savg += chunk_size;

tot_chunks ++;
sample_idx += stsc->entries[i].samplesPerChunk;
if (i+1==stsc->nb_entries) break;
nb_chunk ++;
if (stsc->entries[i].firstChunk + nb_chunk == stsc->entries[i+1].firstChunk) break;
}
}
if (tot_chunks) davg /= tot_chunks;

if (tot_chunks) {
davg /= tot_chunks;
savg /= tot_chunks;
}
if (dur_min) *dur_min = dmin;
if (dur_avg) *dur_avg = (u32) davg;
if (dur_max) *dur_max = dmax;
Expand Down
4 changes: 3 additions & 1 deletion src/gpacmp4/media.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,12 @@ GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp,
//divided into the original and the edition files
if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_READ) {
//same as last call in read mode
if (!mdia->information->dataHandler || (mdia->information->dataEntryIndex != dataRefIndex)) {
if (!mdia->information->dataHandler) {
e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);
if (e) return e;
}
if (mdia->information->dataEntryIndex != dataRefIndex)
mdia->information->dataEntryIndex = dataRefIndex;
} else {
e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);
if (e) return e;
Expand Down
211 changes: 180 additions & 31 deletions src/gpacmp4/mp4.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,87 @@ static int process_avc_track(struct lib_ccx_ctx *ctx, const char* basename, GF_I
return status;
}

unsigned char * ccdp_find_data(unsigned char * ccdp_atom_content, unsigned int len, unsigned int *cc_count)
{
unsigned char *data = ccdp_atom_content;

if (len < 4)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected size of cdp\n");
return NULL;
}

unsigned int cdp_id = (data[0] << 8) | data[1];
if (cdp_id != 0x9669)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected header %hhX %hhX\n", data[0], data[1]);
return NULL;
}

data += 2;
len -= 2;

unsigned int cdp_data_count = data[0];
unsigned int cdp_frame_rate = data[1] >> 4; //frequency could be calculated
if (cdp_data_count != len + 2)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected data length %u %u\n", cdp_data_count, len + 2);
return NULL;
}

data += 2;
len -= 2;

unsigned int cdp_flags = data[0];
unsigned int cdp_counter = (data[1] << 8) | data[2];

data += 3;
len -= 3;

unsigned int cdp_timecode_added = (cdp_flags & 0x80) >> 7;
unsigned int cdp_data_added = (cdp_flags & 0x40) >> 6;

if (!cdp_data_added)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: packet without data\n");
return NULL;
}

if (cdp_timecode_added)
{
data += 4;
len -= 4;
}

if (data[0] != CDP_SECTION_DATA)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: cdp_data_section byte not found\n");
return NULL;
}

*cc_count = (unsigned int) (data[1] & 0x1F);

if (*cc_count != 10 && *cc_count != 20 && *cc_count != 25 && *cc_count != 30)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: unexpected cc_count %u\n", *cc_count);
return NULL;
}

data += 2;
len -= 2;

if ((*cc_count) * 3 > len)
{
dbg_print(CCX_DMT_PARSE, "mp4-708-cdp: not enough bytes left (%u) to carry %u*3 bytes\n", len, *cc_count);
return NULL;
}

(void)(cdp_counter);
(void)(cdp_frame_rate);

return data;
}

/*
Here is application algorithm described in some C-like pseudo code:
main(){
Expand Down Expand Up @@ -231,17 +312,20 @@ int processmp4 (struct lib_ccx_ctx *ctx, char *file,void *enc_ctx)
(unsigned char) ((type>>16)%0x100),(unsigned char) ((type>>8)%0x100),(unsigned char) (type%0x100),
(unsigned char) (subtype>>24%0x100),
(unsigned char) ((subtype>>16)%0x100),(unsigned char) ((subtype>>8)%0x100),(unsigned char) (subtype%0x100));
if (type == GF_ISOM_MEDIA_CAPTIONS && subtype == GF_ISOM_SUBTYPE_C608)
cc_track_count++;
if( type == GF_ISOM_MEDIA_VISUAL && subtype == GF_ISOM_SUBTYPE_AVC_H264)
if ((type == GF_ISOM_MEDIA_CAPTIONS && subtype == GF_ISOM_SUBTYPE_C608) ||
(type == GF_ISOM_MEDIA_CAPTIONS && subtype == GF_ISOM_SUBTYPE_C708))
cc_track_count++;
if (type == GF_ISOM_MEDIA_VISUAL && subtype == GF_ISOM_SUBTYPE_AVC_H264)
avc_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++)
{
const u32 type = gf_isom_get_media_type(f, i + 1);
const u32 subtype = gf_isom_get_media_subtype(f, i + 1, 1);

if ( type == GF_ISOM_MEDIA_VISUAL && subtype == GF_ISOM_SUBTYPE_XDVB)
{
if (cc_track_count && !ccx_options.mp4vidtrack)
Expand Down Expand Up @@ -285,22 +369,20 @@ int processmp4 (struct lib_ccx_ctx *ctx, char *file,void *enc_ctx)


}
if (type == GF_ISOM_MEDIA_CAPTIONS &&
( (subtype == GF_ISOM_SUBTYPE_C608)
//|| (subtype == GF_ISOM_SUBTYPE_C708) && 1)
)
{
if (type == GF_ISOM_MEDIA_CAPTIONS &&
(subtype == GF_ISOM_SUBTYPE_C608 || subtype == GF_ISOM_SUBTYPE_C708))
{
if (avc_track_count && ccx_options.mp4vidtrack)
continue;

#ifdef MP4_DEBUG
unsigned num_streams = gf_isom_get_sample_description_count (f,i+1);
#endif
unsigned num_samples = gf_isom_get_sample_count (f,i+1);

u32 ProcessingStreamDescriptionIndex = 0; // Current track we are processing, 0 = we don't know yet
u32 timescale = gf_isom_get_media_timescale(f,i+1);
#ifdef MP$DEBUG
#ifdef MP4_DEBUG
u64 duration = gf_isom_get_media_duration(f,i+1);
mprint ("%u streams\n",num_streams);
mprint ("%u sample counts\n",num_samples);
Expand All @@ -309,7 +391,7 @@ int processmp4 (struct lib_ccx_ctx *ctx, char *file,void *enc_ctx)
#endif
for (unsigned k = 0; k <num_samples; k++)
{
u32 StreamDescriptionIndex;
u32 StreamDescriptionIndex;
GF_ISOSample *sample= gf_isom_get_sample(f, i+1, k+1, &StreamDescriptionIndex);
if (ProcessingStreamDescriptionIndex && ProcessingStreamDescriptionIndex!=StreamDescriptionIndex)
{
Expand All @@ -336,35 +418,102 @@ int processmp4 (struct lib_ccx_ctx *ctx, char *file,void *enc_ctx)
{
char *data = sample->data + atomStart;
unsigned int atomLength = RB32(data);
if(atomLength < 8 || atomLength > sample->dataLength)
if (atomLength < 8 || atomLength > sample->dataLength)
{
mprint ("Invalid atom.\n");
mprint ("Invalid atom length. Atom length: %u, should be: %u\n", atomLength, sample->dataLength);
break;
}

data += 4;
if (!strncmp(data, "cdat", 4) || !strncmp(data, "cdt2", 4) )
{
int ret = 0;
int len = atomLength - 8;
data += 4;
#ifdef MP4_DEBUG
dump(256, (unsigned char *)data, atomLength - 8, 0, 1);
dump(256, (unsigned char *)data, atomLength - 8, 0, 1);
#endif
do
data += 4;
int is_ccdp = !strncmp(data, "ccdp", 4);

if (!strncmp(data, "cdat", 4) || !strncmp(data, "cdt2", 4) || is_ccdp)
{
if (subtype == GF_ISOM_SUBTYPE_C708)
{
ret = process608((unsigned char*)data, len, ctx->dec_ctx->context_cc608_field_1, &dec_sub);
len -= ret;
data += ret;
if(dec_sub.got_output)
if (!is_ccdp)
{
mprint("Your video file seems to be an interesting sample for us\n");
mprint("We haven't met c708 subtitle not in a \'ccdp\' atom before\n");
mprint("Please, report\n");
break;
}

unsigned int cc_count;
data += 4;
unsigned char *cc_data = ccdp_find_data((unsigned char *) data, sample->dataLength - 8, &cc_count);

if (!cc_data)
{
encode_sub(enc_ctx, &dec_sub);
dec_sub.got_output = 0;
dbg_print(CCX_DMT_PARSE, "mp4-708: no cc data found in ccdp\n");
break;
}
} while (len > 0);

do_cea708 = 1;
unsigned char temp[4];
for (int cc_i = 0; cc_i < cc_count; cc_i++, cc_data += 3)
{
unsigned char cc_info = cc_data[0];
unsigned char cc_valid = (unsigned char) ((cc_info & 4) >> 2);
unsigned char cc_type = (unsigned char) (cc_info & 3);

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");
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");
continue;
}

temp[0] = cc_valid;
temp[1] = cc_type;
temp[2] = cc_data[1];
temp[3] = cc_data[2];

if (cc_type < 2)
{
dbg_print(CCX_DMT_PARSE, "mp4-708: atom skipped (cc_type < 2)\n");
continue;
}
do_708(ctx->dec_ctx, (unsigned char *) temp, 4);
cb_708++;
}
atomStart = sample->dataLength;
}
else //subtype == GF_ISOM_SUBTYPE_C608
{
if (is_ccdp)
{
mprint("Your video file seems to be an interesting sample for us\n");
mprint("We haven't met c608 subtitle in a \'ccdp\' atom before\n");
mprint("Please, report\n");
break;
}

int ret = 0;
int len = atomLength - 8;
data += 4;

do {
ret = process608((unsigned char *) data, len, ctx->dec_ctx->context_cc608_field_1,
&dec_sub);
len -= ret;
data += ret;
if (dec_sub.got_output) {
encode_sub(enc_ctx, &dec_sub);
dec_sub.got_output = 0;
}
} while (len > 0);
}
}
atomStart += atomLength;

}

// End of change
Expand Down
8 changes: 8 additions & 0 deletions src/lib_ccx/ccx_common_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ enum ccx_code_type
CCX_CODEC_ISDB_CC,
CCX_CODEC_NONE,
};

enum cdp_section_type
{
CDP_SECTION_DATA = 0x72,
CDP_SECTION_SVC_INFO = 0x73,
CDP_SECTION_FOOTER = 0x74
};

/*
* This Macro check whether descriptor tag is valid for teletext
* codec or not.
Expand Down