第二种 ffmpeg中的hls解析
/*
* Apple HTTP Live Streaming demuxer
* Copyright (c) 2010 Martin Storsjo
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Apple HTTP Live Streaming demuxer
* http://tools.ietf.org/html/draft-pantos-http-live-streaming
*/
#include "libavutil/avstring.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/dict.h"
#include "libavutil/time.h"
#include "avformat.h"
#include "internal.h"
#include "avio_internal.h"
#include "url.h"
#define INITIAL_BUFFER_SIZE 32768
/*
* An apple http stream consists of a playlist with media segment files,
* played sequentially. There may be several playlists with the same
* video content, in different bandwidth variants, that are played in
* parallel (preferably only one bandwidth variant at a time). In this case,
* the user supplied the url to a main playlist that only lists the variant
* playlists.
*
* If the main playlist doesn't point at any variants, we still create
* one anonymous toplevel variant for this, to maintain the structure.
*/
enum KeyType {
KEY_NONE,
KEY_AES_128,
};
struct segment {
int64_t duration;
char url[MAX_URL_SIZE];
char key[MAX_URL_SIZE];
enum KeyType key_type;
uint8_t iv[16];
};
/*
* Each variant has its own demuxer. If it currently is active,
* it has an open AVIOContext too, and potentially an AVPacket
* containing the next packet from this stream.
*/
struct variant {
int bandwidth;
char url[MAX_URL_SIZE];
AVIOContext pb;
uint8_t* read_buffer;
URLContext *input;
AVFormatContext *parent;
int index;
AVFormatContext *ctx;
AVPacket pkt;
int stream_offset;
int finished;
int64_t target_duration;
int start_seq_no;
int n_segments;
struct segment **segments;
int needed, cur_needed;
int cur_seq_no;
int64_t last_load_time;
char key_url[MAX_URL_SIZE];
uint8_t key[16];
};
typedef struct HLSContext {
int n_variants;
struct variant **variants;
int cur_seq_no;
int end_of_segment;
int first_packet;
int64_t first_timestamp;
int64_t seek_timestamp;
int seek_flags;
AVIOInterruptCB *interrupt_callback;
} HLSContext;
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
{
int len = ff_get_line(s, buf, maxlen);
while (len > 0 && av_isspace(buf[len - 1]))
buf[--len] = '\0';
return len;
}
static void free_segment_list(struct variant *var)
{
int i;
for (i = 0; i < var->n_segments; i++)
av_free(var->segments[i]);
av_freep(&var->segments);
var->n_segments = 0;
}
static void free_variant_list(HLSContext *c)
{
int i;
for (i = 0; i < c->n_variants; i++) {
struct variant *var = c->variants[i];
free_segment_list(var);
av_free_packet(&var->pkt);
av_free(var->pb.buffer);
if (var->input)
ffurl_close(var->input);
if (var->ctx) {
var->ctx->pb = NULL;
avformat_close_input(&var->ctx);
}
av_free(var);
}
av_freep(&c->variants);
c->n_variants = 0;
}
/*
* Used to reset a statically allocated AVPacket to a clean slate,
* containing no data.
*/
static void reset_packet(AVPacket *pkt)
{
av_init_packet(pkt);
pkt->data = NULL;
}
static struct variant *new_variant(HLSContext *c, int bandwidth,
const char *url, const char *base)
{
struct variant *var = av_mallocz(sizeof(struct variant));
if (!var)
return NULL;
reset_packet(&var->pkt);
var->bandwidth = bandwidth;
ff_make_absolute_url(var->url, sizeof(var->url), base, url);
dynarray_add(&c->variants, &c->n_variants, var);
return var;
}
struct variant_info {
char bandwidth[20];
};
static void handle_variant_args(struct variant_info *info, const char *key,
int key_len, char **dest, int *dest_len)
{
if (!strncmp(key, "BANDWIDTH=", key_len)) {
*dest = info->bandwidth;
*dest_len = sizeof(info->bandwidth);
}
}
struct key_info {
char uri[MAX_URL_SIZE];
char method[10];
char iv[35];
};
static void handle_key_args(struct key_info *info, const char *key,
int key_len, char **dest, int *dest_len)
{
if (!strncmp(key, "METHOD=", key_len)) {
*dest = info->method;
*dest_len = sizeof(info->method);
} else if (!strncmp(key, "URI=", key_len)) {
*dest = info->uri;
*dest_len = sizeof(info->uri);
} else if (!strncmp(key, "IV=", key_len)) {
*dest = info->iv;
*dest_len = sizeof(info->iv);
}
}
static int parse_playlist(HLSContext *c, const char