59 int nb_fragments, fragments_size, fragment_index;
93 static int64_t
ism_seek(
void *opaque, int64_t offset,
int whence)
97 if (whence != SEEK_SET)
118 if (offset >= frag->
start_pos && offset < frag->start_pos + frag->
size) {
157 for (i = 0; i <
size; i++)
158 snprintf(&os->
private_str[2*i], 3,
"%02x", ptr[i]);
191 int removed = 0, i, start = 0;
202 if (!
final || removed)
213 char filename[1024], temp_filename[1024];
214 int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0;
217 snprintf(filename,
sizeof(filename),
"%s/Manifest", s->
filename);
218 snprintf(temp_filename,
sizeof(temp_filename),
"%s/Manifest.tmp", s->
filename);
224 avio_printf(out,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
241 video_chunks = audio_chunks = 0;
247 avio_printf(out,
"<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" Duration=\"%"PRIu64
"\"", duration);
252 int last = -1,
index = 0;
253 avio_printf(out,
"<StreamIndex Type=\"video\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", video_streams, video_chunks);
266 int last = -1,
index = 0;
267 avio_printf(out,
"<StreamIndex Type=\"audio\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", audio_streams, audio_chunks);
282 rename(temp_filename, filename);
405 if (*moof_size < 8 || *moof_size > size)
410 if (len > *moof_size)
422 if (len < 8 || len >= *moof_size)
424 if (tag ==
MKTAG(
'u',
'u',
'i',
'd')) {
426 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
427 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
431 if (!memcmp(uuid, tfxd, 16) && len >= 8 + 16 + 4 + 16) {
486 int n =
FFMIN(size,
sizeof(buf));
508 char filename[1024], target_filename[1024], header_filename[1024];
510 int64_t start_ts,
duration, moof_size;
514 snprintf(filename,
sizeof(filename),
"%s/temp", os->
dirname);
530 snprintf(header_filename,
sizeof(header_filename),
"%s/FragmentInfo(%s=%"PRIu64
")", os->
dirname, os->
stream_type_tag, start_ts);
531 snprintf(target_filename,
sizeof(target_filename),
"%s/Fragments(%s=%"PRIu64
")", os->
dirname, os->
stream_type_tag, start_ts);
532 copy_moof(s, filename, header_filename, moof_size);
533 rename(filename, target_filename);
534 add_fragment(os, target_filename, header_filename, start_ts, duration, start_pos,
size);
545 for (j = 0; j <
remove; j++) {
595 snprintf(filename,
sizeof(filename),
"%s/Manifest", s->
filename);
604 #define OFFSET(x) offsetof(SmoothStreamingContext, x)
605 #define E AV_OPT_FLAG_ENCODING_PARAM
607 {
"window_size",
"number of fragments kept in the manifest",
OFFSET(window_size),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
E },
608 {
"extra_window_size",
"number of fragments kept outside of the manifest before removing from disk",
OFFSET(extra_window_size),
AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX,
E },
609 {
"lookahead_count",
"number of lookahead fragments",
OFFSET(lookahead_count),
AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX,
E },
610 {
"min_frag_duration",
"minimum fragment duration (in microseconds)",
OFFSET(min_frag_duration),
AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX,
E },
611 {
"remove_at_exit",
"remove all fragments when finished",
OFFSET(remove_at_exit),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1,
E },
624 .
name =
"smoothstreaming",