202 lines
5.3 KiB
C++
202 lines
5.3 KiB
C++
#ifndef _hls_parser_h_
|
|
#define _hls_parser_h_
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
enum
|
|
{
|
|
HLS_M3U8_UNKNOWN = 0,
|
|
HLS_M3U8_PLAYLIST,
|
|
HLS_M3U8_MASTER,
|
|
};
|
|
|
|
enum
|
|
{
|
|
HLS_PLAYLIST_TYPE_LIVE = 0,
|
|
HLS_PLAYLIST_TYPE_EVENT,
|
|
HLS_PLAYLIST_TYPE_VOD,
|
|
};
|
|
|
|
enum
|
|
{
|
|
HLS_MEDIA_UNKNOWN = 0,
|
|
HLS_MEDIA_AUDIO,
|
|
HLS_MEDIA_VIDEO,
|
|
HLS_MEDIA_SUBTITLE,
|
|
HLS_MEDIA_CLOSED_CAPTIONS,
|
|
};
|
|
|
|
// #EXT-X-MEDIA
|
|
struct hls_media_t
|
|
{
|
|
char* type; // audio/video/subtitle/closed-captions
|
|
char* uri; // Media Playlist file, If the TYPE is CLOSED-CAPTIONS, the URI attribute MUST NOT be present.
|
|
|
|
char* group_id;
|
|
char* language; // RFC5645
|
|
char* assoc_language;
|
|
char* name;
|
|
char* instream_id; // CC1, SERVICE1, for HLS_MEDIA_CLOSED_CAPTIONS
|
|
char* characteristics; // public.accessibility.describes-video
|
|
char* channels; // for HLS_MEDIA_AUDIO
|
|
|
|
int autoselect; // 1-YES, 0-NO
|
|
int is_default; // 1-YES, 0-NO
|
|
int forced; // 1-YES, 0-NO, SUBTITLES only
|
|
};
|
|
|
|
// #EXT-X-STREAM-INF
|
|
struct hls_variant_t
|
|
{
|
|
uint32_t bandwidth; // the peak segment bit rate of the Variant Stream
|
|
uint32_t average_bandwidth; // the average segment bit rate of the Variant Stream
|
|
int width, height; // resolution
|
|
double fps; // frame-rate
|
|
char* hdcp_level; // TYPE-0
|
|
char* uri;
|
|
char* codecs; // RFC6381, mp4a.40.2,avc1.4d401e
|
|
char* video_range; // SDR/PQ
|
|
char* audio; // GROUP-ID of EXT-X-MEDIA
|
|
char* video; // GROUP-ID of EXT-X-MEDIA
|
|
char* subtitle; // GROUP-ID of EXT-X-MEDIA
|
|
char* closed_captions; // GROUP-ID of EXT-X-MEDIA
|
|
|
|
struct hls_variant_t* i_frame_stream_inf; // EXT-X-I-FRAME-STREAM-INF
|
|
};
|
|
|
|
struct hls_segment_t
|
|
{
|
|
double duration;
|
|
char* uri;
|
|
char* title;
|
|
|
|
int64_t bytes; // EXT-X-BYTERANGE, -1 if don't exist
|
|
int64_t offset; // EXT-X-BYTERANGE, -1 if don't exist
|
|
|
|
// 1. file format
|
|
// 2. number, type, and identifiers of tracks
|
|
// 3. timestamp sequence
|
|
// 4. encoding parameters
|
|
// 5. encoding sequence
|
|
int discontinuity; // EXT-X-DISCONTINUITY
|
|
|
|
struct {
|
|
char* method; // NONE, AES-128, and SAMPLE-AES
|
|
char* uri;
|
|
char* keyformat; // identity
|
|
char* keyformatversions; // "1", "1/2", "1/2/5"
|
|
uint8_t iv[16]; // 128bits
|
|
} key; // EXT-X-KEY
|
|
|
|
// It applies to every Media Segment that appears after it in the
|
|
// Playlist until the next EXT-X-MAP tag or until the end of the Playlist.
|
|
struct {
|
|
char* uri;
|
|
int64_t bytes; // BYTERANGE, -1 if don't exist
|
|
int64_t offset; // BYTERANGE, -1 if don't exist
|
|
} map; // EXT-X-MAP
|
|
|
|
char* program_date_time; // EXT-X-PROGRAM-DATE-TIME
|
|
|
|
struct {
|
|
char* id;
|
|
char* cls;
|
|
char* start_date;
|
|
char* end_date;
|
|
double duration; // decimal-floating-point number of seconds
|
|
double planned_duration; // decimal-floating-point number of seconds
|
|
char* x_client_attribute; // TODO
|
|
int end_on_next; // 1-YES, 0-NO
|
|
} daterange; // EXT-X-DATERANGE
|
|
};
|
|
|
|
// If the Media Playlist contains the EXT-X-MEDIA-SEQUENCE tag, the
|
|
// client SHOULD assume that each Media Segment in it will become
|
|
// unavailable at the time that the Playlist file was loaded plus the
|
|
// duration of the Playlist file.
|
|
struct hls_playlist_t
|
|
{
|
|
int version;
|
|
|
|
uint64_t target_duration; // EXT-X-TARGETDURATION, seconds
|
|
uint64_t media_sequence; // EXT-X-MEDIA-SEQUENCE, base from 0
|
|
uint64_t discontinuity_sequence; // EXT-X-DISCONTINUITY-SEQUENCE, decimal-integer
|
|
int endlist; // EXT-X-ENDLIST, 1-endlist, 0-don't have endlist
|
|
int type; // EXT-X-PLAYLIST-TYPE, 0-LIVE, 1-EVENT, 2-VOD
|
|
int i_frames_only; // EXT-X-I-FRAMES-ONLY
|
|
int independent_segments; // EXT-X-INDEPENDENT-SEGMENTS
|
|
double start_time_offset; // EXT-X-START, seconds
|
|
int start_precise; // EXT-X-START
|
|
|
|
struct hls_segment_t* segments;
|
|
size_t count;
|
|
};
|
|
|
|
struct hls_master_t
|
|
{
|
|
int version;
|
|
|
|
size_t variant_count;
|
|
struct hls_variant_t *variants;
|
|
|
|
// renditions: audio, video, subtitle, close_captions
|
|
size_t media_count;
|
|
struct hls_media_t* medias;
|
|
|
|
struct {
|
|
char* data_id;
|
|
char* value;
|
|
char* uri;
|
|
char* language;
|
|
} *session_data;
|
|
size_t session_data_count;
|
|
|
|
struct {
|
|
char* method; // NONE, AES-128, and SAMPLE-AES
|
|
char* uri;
|
|
char* keyformat; // identity
|
|
char* keyformatversions; // "1", "1/2", "1/2/5"
|
|
uint8_t iv[16]; // 128bits
|
|
} *session_key; // EXT-X-SESSION-KEY
|
|
size_t session_key_count;
|
|
|
|
int independent_segments; // EXT-X-INDEPENDENT-SEGMENTS
|
|
double start_time_offset; // EXT-X-START
|
|
int start_precise; // EXT-X-START
|
|
};
|
|
|
|
/// Probe m3u8 content type
|
|
/// @return HLS_M3U8_PLAYLIST-media playlist, HLS_M3U8_MASTER-master playlist, other-unknown
|
|
int hls_parser_probe(const char* m3u8, size_t len);
|
|
|
|
/// Parse m3u8 master playlist
|
|
/// @param[out] master m3u8 master playlist(free by hls_master_free)
|
|
/// @return 0-ok, other-error
|
|
int hls_master_parse(struct hls_master_t** master, const char* m3u8, size_t len);
|
|
|
|
int hls_master_free(struct hls_master_t** master);
|
|
|
|
int hls_master_best_variant(const struct hls_master_t* master);
|
|
|
|
int hls_master_rendition(const struct hls_master_t* master, int variant, int type, const char* name);
|
|
|
|
/// Parse m3u8 media playlist
|
|
/// @param[out] playlist m3u8 media playlist(free by hls_playlist_free)
|
|
/// @return 0-ok, other-error
|
|
int hls_playlist_parse(struct hls_playlist_t** playlist, const char* m3u8, size_t len);
|
|
|
|
int hls_playlist_free(struct hls_playlist_t** playlist);
|
|
|
|
/// @return total duration in MS
|
|
int64_t hls_playlist_duration(const struct hls_playlist_t* playlist);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* !_hls_parser_h_ */
|