Skip to content

Commit 274ab1f

Browse files
committed
add support key frame positions in mapping json
make is possible to align the segments to keyframes while having accurate segment durations in the manifest.
1 parent 59984a7 commit 274ab1f

14 files changed

+526
-281
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,14 @@ Optional fields:
420420
* `label` - a friendly string that identifies the sequence. if a language is specified,
421421
a default label will be automatically derived by it - e.g. if language is `ita`,
422422
by default `italiano` will be used as the label.
423+
* `keyFrameDurations` - array of integers, containing the durations of the video key frames
424+
in the sequence. Supplying the key frame durations enables the module to both:
425+
1. align the segments to key frames
426+
2. report the correct segment durations in the manifest - providing an alternative to setting
427+
`vod_manifest_segment_durations_mode` to `accurate`, which is not supported for multi clip
428+
media sets (for performance reasons).
429+
* `firstKeyFrameOffset` - integer, offset of the first video key frame in the sequence,
430+
measured in milliseconds relative to `firstClipTime`. Defaults to 0 if not supplied.
423431

424432
#### Clip (abstract)
425433

ngx_http_vod_module.c

+12-8
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,7 @@ ngx_http_vod_parse_metadata(
986986
ngx_http_vod_ctx_t *ctx,
987987
ngx_flag_t fetched_from_cache)
988988
{
989+
get_clip_ranges_params_t get_ranges_params;
989990
media_parse_params_t parse_params;
990991
const ngx_http_vod_request_t* request = ctx->request;
991992
media_clip_source_t* cur_source = ctx->cur_source;
@@ -1143,15 +1144,18 @@ ngx_http_vod_parse_metadata(
11431144
// get the start/end offsets
11441145
duration_millis = rescale_time(ctx->base_metadata->duration * rate.denom, ctx->base_metadata->timescale * rate.nom, 1000);
11451146

1147+
get_ranges_params.request_context = &ctx->submodule_context.request_context,
1148+
get_ranges_params.conf = segmenter,
1149+
get_ranges_params.segment_index = ctx->submodule_context.request_params.segment_index,
1150+
get_ranges_params.clip_durations = &duration_millis,
1151+
get_ranges_params.total_clip_count = 1,
1152+
get_ranges_params.start_time = 0,
1153+
get_ranges_params.end_time = duration_millis,
1154+
get_ranges_params.last_segment_end = last_segment_end,
1155+
get_ranges_params.key_frame_durations = NULL;
1156+
11461157
rc = segmenter_get_start_end_ranges_no_discontinuity(
1147-
&ctx->submodule_context.request_context,
1148-
segmenter,
1149-
ctx->submodule_context.request_params.segment_index,
1150-
&duration_millis,
1151-
1,
1152-
0,
1153-
duration_millis,
1154-
last_segment_end,
1158+
&get_ranges_params,
11551159
&clip_ranges);
11561160
if (rc != VOD_OK)
11571161
{

ngx_http_vod_request_parse.c

+2
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,8 @@ ngx_http_vod_parse_uri_path(
909909
cur_sequence->id.len = 0;
910910
cur_sequence->language = 0;
911911
cur_sequence->label.len = 0;
912+
cur_sequence->first_key_frame_offset = 0;
913+
cur_sequence->key_frame_durations = NULL;
912914

913915
cur_source++;
914916
cur_sequence++;

test/playlist.php

+39-11
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,43 @@
88
exactly the same encoding parameters (in the case of h264, the SPS/PPS have to be the same).
99
*/
1010

11+
function getRequestParams()
12+
{
13+
$scriptParts = explode('/', $_SERVER['SCRIPT_NAME']);
14+
$pathParts = array();
15+
if (isset($_SERVER['PHP_SELF']))
16+
$pathParts = explode('/', $_SERVER['PHP_SELF']);
17+
$pathParts = array_diff($pathParts, $scriptParts);
18+
19+
$params = array();
20+
reset($pathParts);
21+
while(current($pathParts))
22+
{
23+
$key = each($pathParts);
24+
$value = each($pathParts);
25+
if (!array_key_exists($key['value'], $params))
26+
{
27+
$params[$key['value']] = $value['value'];
28+
}
29+
}
30+
return $params;
31+
}
32+
33+
$params = getRequestParams();
34+
$discontinuity = (isset($params['disc']) && $params['disc']) ? true : false;
35+
$playlistType = isset($params['type']) ? $params['type'] : "live";
36+
1137
// input params
12-
$playlistType = "live"; // live / vod
13-
$discontinuity = true;
1438
$filePaths = array(
1539
"/path/to/video1.mp4",
1640
"/path/to/video2.mp4",
1741
"/path/to/video3.mp4",
1842
);
19-
$ffprobeBin = '/path/to/ffprobe.sh';
43+
if (!$discontinuity)
44+
{
45+
$filePaths = array($filePaths[0], $filePaths[0]);
46+
}
47+
$ffprobeBin = '/web/content/shared/bin/ffmpeg-2.7.2-bin/ffprobe.sh';
2048
$timeMargin = 10000; // a safety margin to compensate for clock differences
2149

2250
// nginx conf params
@@ -86,18 +114,19 @@ function getDurationMillis($filePath)
86114

87115
// start the playlist from now() - <dvr window size>
88116
$currentTime = time() * 1000 - $timeMargin - $dvrWindowSize;
89-
90-
// set the first clip time to now() rounded down to cycle duration
91-
$result["firstClipTime"] = floor($currentTime / $cycleDuration) * $cycleDuration;
92-
93-
// get the reference time (the first clip time of the first run)
117+
118+
// get the reference time (the time of the first run)
94119
$referenceTime = apc_fetch('reference_time');
95120
if (!$referenceTime)
96121
{
97-
$referenceTime = $result["firstClipTime"];
122+
$referenceTime = $currentTime;
98123
apc_store('reference_time', $referenceTime);
99124
}
100-
125+
126+
// set the first clip time to now() rounded down to cycle duration
127+
$cycleIndex = floor(($currentTime - $referenceTime) / $cycleDuration);
128+
$result["firstClipTime"] = $referenceTime + $cycleIndex * $cycleDuration;
129+
101130
if ($discontinuity)
102131
{
103132
// find the total number of segments in each cycle
@@ -108,7 +137,6 @@ function getDurationMillis($filePath)
108137
}
109138

110139
// find the initial clip index and initial segment index
111-
$cycleIndex = floor(($currentTime - $referenceTime) / $cycleDuration);
112140
$result["initialClipIndex"] = $cycleIndex * count($durations) + 1;
113141
$result["initialSegmentIndex"] = $cycleIndex * $totalSegmentCount + 1;
114142
}

vod/common.h

+7
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@ enum {
264264
VOD_ERROR_LAST,
265265
};
266266

267+
typedef struct vod_array_part_s {
268+
void* first;
269+
void* last;
270+
size_t count;
271+
struct vod_array_part_s* next;
272+
} vod_array_part_t;
273+
267274
typedef vod_status_t(*write_callback_t)(void* context, u_char* buffer, uint32_t size);
268275

269276
typedef struct {

vod/filters/concat_clip.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ concat_clip_parse(
4343
void** result)
4444
{
4545
media_filter_parse_context_t* context = ctx;
46-
vod_json_array_part_t* first_part = NULL;
47-
vod_json_array_part_t* part;
46+
vod_array_part_t* first_part = NULL;
47+
vod_array_part_t* part;
4848
media_clip_source_t* sources_list_head;
4949
media_clip_source_t* cur_source;
5050
media_clip_source_t* sources_end;

vod/json_parser.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ vod_json_parse_fraction(vod_json_parser_state_t* state, vod_json_fraction_t* res
321321
static vod_json_status_t
322322
vod_json_parse_array(vod_json_parser_state_t* state, vod_json_array_t* result)
323323
{
324-
vod_json_array_part_t* part;
324+
vod_array_part_t* part;
325325
vod_json_type_t* type;
326326
size_t initial_part_count;
327327
size_t part_size;

vod/json_parser.h

+1-8
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,10 @@ typedef struct {
3131
uint64_t denom;
3232
} vod_json_fraction_t;
3333

34-
typedef struct vod_json_array_part_s {
35-
void* first;
36-
void* last;
37-
size_t count;
38-
struct vod_json_array_part_s* next;
39-
} vod_json_array_part_t;
40-
4134
typedef struct {
4235
int type;
4336
size_t count;
44-
vod_json_array_part_t part;
37+
vod_array_part_t part;
4538
} vod_json_array_t;
4639

4740
typedef vod_array_t vod_json_object_t;

vod/media_format.h

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#define MAX_FRAME_SIZE (10 * 1024 * 1024)
1717
#define MAX_TRACK_COUNT (1024)
1818
#define MAX_DURATION_SEC (1000000)
19+
#define MAX_CLIP_DURATION (86400000) // 1 day
20+
#define MAX_SEQUENCE_DURATION (864000000) // 10 days
1921

2022
// parse flags
2123

vod/media_set.h

+3
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@ typedef struct {
4444
struct media_sequence_s {
4545
// initialized during parsing
4646
uint32_t index;
47+
vod_array_part_t* unparsed_clips;
4748
media_clip_t** clips; // [clip_count]
4849
vod_str_t stripped_uri;
4950
vod_str_t id;
5051
vod_str_t label;
5152
language_id_t language;
53+
int64_t first_key_frame_offset;
54+
vod_array_part_t* key_frame_durations;
5255

5356
// initialized after mapping
5457
vod_str_t mapped_uri;

0 commit comments

Comments
 (0)