60 fprintf(stderr,
"%s [-split] [-ismf] [-n basename] [-path-prefix prefix] "
61 "[-ismc-prefix prefix] [-output dir] file1 [file2] ...\n", argv0);
98 if (got_tag != expected_tag) {
99 char got_tag_str[4], expected_tag_str[4];
101 AV_WB32(expected_tag_str, expected_tag);
102 fprintf(stderr,
"wanted tag %.4s, got %.4s\n", expected_tag_str,
124 if ((got =
avio_read(in, buf, len)) != len) {
125 fprintf(stderr,
"short read, wanted %d, got %d\n", len, got);
155 fprintf(stderr,
"Unable to open %s: %s\n", filename, errbuf);
179 int split,
int ismf,
const char* output_prefix)
181 char dirname[2048], filename[2048], idxname[2048];
182 int i, j,
ret = 0, fragment_ret;
186 snprintf(idxname,
sizeof(idxname),
"%s%s.ismf", output_prefix, basename);
187 out = fopen(idxname,
"w");
194 for (i = start_index; i < tracks->
nb_tracks; i++) {
197 snprintf(dirname,
sizeof(dirname),
"%sQualityLevels(%d)", output_prefix, track->
bitrate);
199 if (mkdir(dirname, 0777) == -1 && errno != EEXIST) {
205 for (j = 0; j < track->
chunks; j++) {
206 snprintf(filename,
sizeof(filename),
"%s/Fragments(%s=%"PRId64
")",
210 fprintf(out,
"%s %"PRId64, filename,
avio_tell(in));
216 fprintf(out,
" %"PRId64
"\n",
avio_tell(in));
217 if (fragment_ret != 0) {
218 fprintf(stderr,
"failed fragment %d in track %d (%s)\n", j,
240 fprintf(stderr,
"No sample duration in trun flags\n");
249 for (i = 0; i < entries && pos <
end; i++) {
250 int sample_duration = default_duration;
251 if (flags & MOV_TRUN_SAMPLE_DURATION) sample_duration =
avio_rb32(in);
255 if (sample_duration < 0) {
256 fprintf(stderr,
"Negative sample duration %d\n", sample_duration);
259 ret += sample_duration;
271 int default_duration = 0;
278 while (pos < offset + moof_size) {
282 if (tag ==
MKBETAG(
't',
'r',
'a',
'f')) {
283 int64_t traf_pos = pos;
284 int64_t traf_size =
size;
285 while (pos < traf_pos + traf_size) {
289 if (tag ==
MKBETAG(
't',
'f',
'h',
'd')) {
301 if (tag ==
MKBETAG(
't',
'r',
'u',
'n')) {
307 fprintf(stderr,
"Couldn't find trun\n");
312 fprintf(stderr,
"Couldn't find traf\n");
321 int version, fieldlength, i, j;
324 struct Track *track = NULL;
331 for (i = start_index; i < tracks->
nb_tracks && !track; i++)
333 track = tracks->
tracks[i];
348 for (i = 0; i < track->
chunks; i++) {
356 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
358 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
360 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
372 for (i = 0; i < track->
chunks; i++) {
382 fprintf(stderr,
"Calculated last chunk duration for track %d "
383 "was non-positive (%"PRId64
"), probably due to missing "
392 fprintf(stderr,
"corrected to %"PRId64
"\n",
397 fprintf(stderr,
"Track duration corrected to %"PRId64
"\n",
409 const char *file,
int split,
int ismf,
410 const char *basename,
const char* output_prefix)
413 const char* err_str =
"";
424 err_str =
"mfra size mismatch";
429 err_str =
"mfra tag mismatch";
432 while (!
read_tfra(tracks, start_index, f)) {
439 err_str =
"error in write_fragments";
445 fprintf(stderr,
"Unable to read the MFRA atom in %s (%s)\n", file, err_str);
462 uint16_t sps_size, pps_size;
491 int ismf,
const char *basename,
492 const char* output_prefix)
495 int err = 0, i, orig_tracks = tracks->
nb_tracks;
496 char errbuf[50], *ptr;
502 fprintf(stderr,
"Unable to open %s: %s\n", file, errbuf);
509 fprintf(stderr,
"Unable to identify %s: %s\n", file, errbuf);
514 fprintf(stderr,
"No streams found in %s\n", file);
523 fprintf(stderr,
"Skipping track %d in %s as it has zero bitrate\n",
544 if ((ptr = strrchr(file,
'/')))
545 track->
name = ptr + 1;
556 "Track %d in %s is neither video nor audio, skipping\n",
601 err =
read_mfra(tracks, orig_tracks, file, split, ismf, basename,
611 const char *output_prefix,
612 const char *path_prefix,
613 const char *ismc_prefix)
619 snprintf(filename,
sizeof(filename),
"%s%s.ism", output_prefix, basename);
620 out = fopen(filename,
"w");
625 fprintf(out,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
626 fprintf(out,
"<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
627 fprintf(out,
"\t<head>\n");
628 fprintf(out,
"\t\t<meta name=\"clientManifestRelativePath\" "
629 "content=\"%s%s.ismc\" />\n", ismc_prefix, basename);
630 fprintf(out,
"\t</head>\n");
631 fprintf(out,
"\t<body>\n");
632 fprintf(out,
"\t\t<switch>\n");
633 for (i = 0; i < tracks->
nb_tracks; i++) {
636 fprintf(out,
"\t\t\t<%s src=\"%s%s\" systemBitrate=\"%d\">\n",
638 fprintf(out,
"\t\t\t\t<param name=\"trackID\" value=\"%d\" "
639 "valueType=\"data\" />\n", track->
track_id);
640 fprintf(out,
"\t\t\t</%s>\n", type);
642 fprintf(out,
"\t\t</switch>\n");
643 fprintf(out,
"\t</body>\n");
644 fprintf(out,
"</smil>\n");
654 int should_print_time_mismatch = 1;
656 for (i = 0; i < track->
chunks; i++) {
657 for (j = main + 1; j < tracks->
nb_tracks; j++) {
660 fprintf(stderr,
"Mismatched duration of %s chunk %d in %s (%d) and %s (%d)\n",
662 should_print_time_mismatch = 1;
665 if (should_print_time_mismatch)
666 fprintf(stderr,
"Mismatched (start) time of %s chunk %d in %s (%d) and %s (%d)\n",
668 should_print_time_mismatch = 0;
672 fprintf(out,
"\t\t<c n=\"%d\" d=\"%"PRId64
"\" ",
675 fprintf(out,
"t=\"%"PRId64
"\" ", track->
offsets[i].
time);
679 fprintf(out,
"/>\n");
684 const char *output_prefix,
int split)
691 snprintf(filename,
sizeof(filename),
"%sManifest", output_prefix);
693 snprintf(filename,
sizeof(filename),
"%s%s.ismc", output_prefix, basename);
694 out = fopen(filename,
"w");
699 fprintf(out,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
700 fprintf(out,
"<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" "
701 "Duration=\"%"PRId64
"\">\n", tracks->
duration * 10);
704 struct Track *first_track = track;
707 "\t<StreamIndex Type=\"video\" QualityLevels=\"%d\" "
709 "Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n",
711 for (i = 0; i < tracks->
nb_tracks; i++) {
712 track = tracks->
tracks[i];
716 "\t\t<QualityLevel Index=\"%d\" Bitrate=\"%d\" "
717 "FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" "
718 "CodecPrivateData=\"",
722 fprintf(out,
"\" />\n");
725 fprintf(stderr,
"Mismatched number of video chunks in %s (id: %d, chunks %d) and %s (id: %d, chunks %d)\n",
729 fprintf(out,
"\t</StreamIndex>\n");
733 struct Track *first_track = track;
736 "\t<StreamIndex Type=\"audio\" QualityLevels=\"%d\" "
738 "Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n",
740 for (i = 0; i < tracks->
nb_tracks; i++) {
741 track = tracks->
tracks[i];
745 "\t\t<QualityLevel Index=\"%d\" Bitrate=\"%d\" "
746 "FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" "
747 "BitsPerSample=\"16\" PacketSize=\"%d\" "
748 "AudioTag=\"%d\" CodecPrivateData=\"",
753 fprintf(out,
"\" />\n");
756 fprintf(stderr,
"Mismatched number of audio chunks in %s and %s\n",
760 fprintf(out,
"\t</StreamIndex>\n");
762 fprintf(out,
"</SmoothStreamingMedia>\n");
769 for (i = 0; i < tracks->
nb_tracks; i++) {
778 int main(
int argc,
char **argv)
780 const char *basename = NULL;
781 const char *path_prefix =
"", *ismc_prefix =
"";
782 const char *output_prefix =
"";
783 char output_prefix_buf[2048];
784 int split = 0, ismf = 0, i;
789 for (i = 1; i < argc; i++) {
790 if (!strcmp(argv[i],
"-n")) {
791 basename = argv[i + 1];
793 }
else if (!strcmp(argv[i],
"-path-prefix")) {
794 path_prefix = argv[i + 1];
796 }
else if (!strcmp(argv[i],
"-ismc-prefix")) {
797 ismc_prefix = argv[i + 1];
799 }
else if (!strcmp(argv[i],
"-output")) {
800 output_prefix = argv[i + 1];
802 if (output_prefix[strlen(output_prefix) - 1] !=
'/') {
803 snprintf(output_prefix_buf,
sizeof(output_prefix_buf),
804 "%s/", output_prefix);
805 output_prefix = output_prefix_buf;
807 }
else if (!strcmp(argv[i],
"-split")) {
809 }
else if (!strcmp(argv[i],
"-ismf")) {
811 }
else if (argv[i][0] ==
'-') {
812 return usage(argv[0], 1);
817 basename, output_prefix))
821 if (!tracks.
nb_tracks || (!basename && !split))
822 return usage(argv[0], 1);
826 path_prefix, ismc_prefix);