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;
331 for (i = start_index; i < tracks->
nb_tracks && !track; i++)
333 track = tracks->
tracks[i];
349 for (i = 0; i < track->
chunks; i++) {
357 for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++)
359 for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++)
361 for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++)
373 for (i = 0; i < track->
chunks; i++) {
383 fprintf(stderr,
"Calculated last chunk duration for track %d "
384 "was non-positive (%"PRId64
"), probably due to missing "
393 fprintf(stderr,
"corrected to %"PRId64
"\n",
398 fprintf(stderr,
"Track duration corrected to %"PRId64
"\n",
410 const char *file,
int split,
int ismf,
411 const char *basename,
const char* output_prefix)
414 const char* err_str =
"";
425 err_str =
"mfra size mismatch";
430 err_str =
"mfra tag mismatch";
433 while (!
read_tfra(tracks, start_index, f)) {
440 err_str =
"error in write_fragments";
446 fprintf(stderr,
"Unable to read the MFRA atom in %s (%s)\n", file, err_str);
464 uint16_t sps_size, pps_size;
493 int ismf,
const char *basename,
494 const char* output_prefix)
497 int err = 0, i, orig_tracks = tracks->
nb_tracks;
498 char errbuf[50], *ptr;
504 fprintf(stderr,
"Unable to open %s: %s\n", file, errbuf);
511 fprintf(stderr,
"Unable to identify %s: %s\n", file, errbuf);
516 fprintf(stderr,
"No streams found in %s\n", file);
525 fprintf(stderr,
"Skipping track %d in %s as it has zero bitrate\n",
547 if ((ptr = strrchr(file,
'/')))
548 track->
name = ptr + 1;
559 "Track %d in %s is neither video nor audio, skipping\n",
604 err =
read_mfra(tracks, orig_tracks, file, split, ismf, basename,
614 const char *output_prefix,
615 const char *path_prefix,
616 const char *ismc_prefix)
622 snprintf(filename,
sizeof(filename),
"%s%s.ism", output_prefix, basename);
623 out = fopen(filename,
"w");
628 fprintf(out,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
629 fprintf(out,
"<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n");
630 fprintf(out,
"\t<head>\n");
631 fprintf(out,
"\t\t<meta name=\"clientManifestRelativePath\" "
632 "content=\"%s%s.ismc\" />\n", ismc_prefix, basename);
633 fprintf(out,
"\t</head>\n");
634 fprintf(out,
"\t<body>\n");
635 fprintf(out,
"\t\t<switch>\n");
636 for (i = 0; i < tracks->
nb_tracks; i++) {
639 fprintf(out,
"\t\t\t<%s src=\"%s%s\" systemBitrate=\"%d\">\n",
641 fprintf(out,
"\t\t\t\t<param name=\"trackID\" value=\"%d\" "
642 "valueType=\"data\" />\n", track->
track_id);
643 fprintf(out,
"\t\t\t</%s>\n", type);
645 fprintf(out,
"\t\t</switch>\n");
646 fprintf(out,
"\t</body>\n");
647 fprintf(out,
"</smil>\n");
657 int should_print_time_mismatch = 1;
659 for (i = 0; i < track->
chunks; i++) {
660 for (j = main + 1; j < tracks->
nb_tracks; j++) {
663 fprintf(stderr,
"Mismatched duration of %s chunk %d in %s (%d) and %s (%d)\n",
665 should_print_time_mismatch = 1;
668 if (should_print_time_mismatch)
669 fprintf(stderr,
"Mismatched (start) time of %s chunk %d in %s (%d) and %s (%d)\n",
671 should_print_time_mismatch = 0;
675 fprintf(out,
"\t\t<c n=\"%d\" d=\"%"PRId64
"\" ",
678 fprintf(out,
"t=\"%"PRId64
"\" ", track->
offsets[i].
time);
682 fprintf(out,
"/>\n");
687 const char *output_prefix,
int split)
694 snprintf(filename,
sizeof(filename),
"%sManifest", output_prefix);
696 snprintf(filename,
sizeof(filename),
"%s%s.ismc", output_prefix, basename);
697 out = fopen(filename,
"w");
702 fprintf(out,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
703 fprintf(out,
"<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" "
704 "Duration=\"%"PRId64
"\">\n", tracks->
duration * 10);
707 struct Track *first_track = track;
710 "\t<StreamIndex Type=\"video\" QualityLevels=\"%d\" "
712 "Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n",
714 for (i = 0; i < tracks->
nb_tracks; i++) {
715 track = tracks->
tracks[i];
719 "\t\t<QualityLevel Index=\"%d\" Bitrate=\"%d\" "
720 "FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" "
721 "CodecPrivateData=\"",
725 fprintf(out,
"\" />\n");
728 fprintf(stderr,
"Mismatched number of video chunks in %s (id: %d, chunks %d) and %s (id: %d, chunks %d)\n",
732 fprintf(out,
"\t</StreamIndex>\n");
736 struct Track *first_track = track;
739 "\t<StreamIndex Type=\"audio\" QualityLevels=\"%d\" "
741 "Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n",
743 for (i = 0; i < tracks->
nb_tracks; i++) {
744 track = tracks->
tracks[i];
748 "\t\t<QualityLevel Index=\"%d\" Bitrate=\"%d\" "
749 "FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" "
750 "BitsPerSample=\"16\" PacketSize=\"%d\" "
751 "AudioTag=\"%d\" CodecPrivateData=\"",
756 fprintf(out,
"\" />\n");
759 fprintf(stderr,
"Mismatched number of audio chunks in %s and %s\n",
763 fprintf(out,
"\t</StreamIndex>\n");
765 fprintf(out,
"</SmoothStreamingMedia>\n");
772 for (i = 0; i < tracks->
nb_tracks; i++) {
781 int main(
int argc,
char **argv)
783 const char *basename =
NULL;
784 const char *path_prefix =
"", *ismc_prefix =
"";
785 const char *output_prefix =
"";
786 char output_prefix_buf[2048];
787 int split = 0, ismf = 0, i;
792 for (i = 1; i < argc; i++) {
793 if (!strcmp(argv[i],
"-n")) {
794 basename = argv[i + 1];
796 }
else if (!strcmp(argv[i],
"-path-prefix")) {
797 path_prefix = argv[i + 1];
799 }
else if (!strcmp(argv[i],
"-ismc-prefix")) {
800 ismc_prefix = argv[i + 1];
802 }
else if (!strcmp(argv[i],
"-output")) {
803 output_prefix = argv[i + 1];
805 if (output_prefix[strlen(output_prefix) - 1] !=
'/') {
806 snprintf(output_prefix_buf,
sizeof(output_prefix_buf),
807 "%s/", output_prefix);
808 output_prefix = output_prefix_buf;
810 }
else if (!strcmp(argv[i],
"-split")) {
812 }
else if (!strcmp(argv[i],
"-ismf")) {
814 }
else if (argv[i][0] ==
'-') {
815 return usage(argv[0], 1);
820 basename, output_prefix))
824 if (!tracks.
nb_tracks || (!basename && !split))
825 return usage(argv[0], 1);
829 path_prefix, ismc_prefix);