summaryrefslogtreecommitdiff
path: root/libavformat/hlsenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/hlsenc.c')
-rw-r--r--libavformat/hlsenc.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 39ff1fa1e7..cb31d6aed7 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -69,6 +69,7 @@ typedef enum {
#define KEYSIZE 16
#define LINE_BUFFER_SIZE MAX_URL_SIZE
#define HLS_MICROSECOND_UNIT 1000000
+#define BUFSIZE (16 * 1024)
#define POSTFIX_PATTERN "_%d"
typedef struct HLSSegment {
@@ -119,6 +120,7 @@ typedef struct VariantStream {
ff_const59 AVOutputFormat *oformat;
ff_const59 AVOutputFormat *vtt_oformat;
AVIOContext *out;
+ AVIOContext *out_single_file;
int packets_written;
int init_range_length;
uint8_t *temp_buffer;
@@ -149,6 +151,7 @@ typedef struct VariantStream {
HLSSegment *last_segment;
HLSSegment *old_segments;
+ char *basename_tmp;
char *basename;
char *vtt_basename;
char *vtt_m3u8_name;
@@ -1722,12 +1725,34 @@ static int hls_start(AVFormatContext *s, VariantStream *vs)
av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0);
}
if (c->flags & HLS_SINGLE_FILE) {
+ if (c->key_info_file || c->encrypt) {
+ av_dict_set(&options, "encryption_key", vs->key_string, 0);
+ av_dict_set(&options, "encryption_iv", vs->iv_string, 0);
+
+ /* Write temp file with cryption content */
+ av_freep(&vs->basename_tmp);
+ vs->basename_tmp = av_asprintf("crypto:%s.tmp", oc->url);
+
+ /* append temp file content into single file */
+ av_freep(&vs->basename);
+ vs->basename = av_asprintf("%s", oc->url);
+ } else {
+ vs->basename_tmp = vs->basename;
+ }
set_http_options(s, &options, c);
- if ((err = hlsenc_io_open(s, &vs->out, oc->url, &options)) < 0) {
+ if (!vs->out_single_file)
+ if ((err = hlsenc_io_open(s, &vs->out_single_file, vs->basename, &options)) < 0) {
+ if (c->ignore_io_errors)
+ err = 0;
+ goto fail;
+ }
+
+ if ((err = hlsenc_io_open(s, &vs->out, vs->basename_tmp, &options)) < 0) {
if (c->ignore_io_errors)
err = 0;
goto fail;
}
+
}
}
if (vs->vtt_basename) {
@@ -2258,6 +2283,38 @@ static int hls_init_file_resend(AVFormatContext *s, VariantStream *vs)
return ret;
}
+static int64_t append_single_file(AVFormatContext *s, VariantStream *vs)
+{
+ int ret = 0;
+ int64_t read_byte = 0;
+ int64_t total_size = 0;
+ char *filename = NULL;
+ char buf[BUFSIZE];
+ AVFormatContext *oc = vs->avf;
+
+ hlsenc_io_close(s, &vs->out, vs->basename_tmp);
+ filename = av_asprintf("%s.tmp", oc->url);
+ ret = s->io_open(s, &vs->out, filename, AVIO_FLAG_READ, NULL);
+ if (ret < 0) {
+ av_free(filename);
+ return ret;
+ }
+
+ do {
+ memset(buf, 0, sizeof(BUFSIZE));
+ read_byte = avio_read(vs->out, buf, BUFSIZE);
+ avio_write(vs->out_single_file, buf, read_byte);
+ if (read_byte > 0) {
+ total_size += read_byte;
+ ret = total_size;
+ }
+ } while (read_byte > 0);
+
+ hlsenc_io_close(s, &vs->out, filename);
+ av_free(filename);
+
+ return ret;
+}
static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
{
HLSContext *hls = s->priv_data;
@@ -2383,6 +2440,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
return ret;
}
vs->size = range_length;
+ if (hls->key_info_file || hls->encrypt)
+ vs->size = append_single_file(s, vs);
} else {
if (oc->url[0]) {
proto = avio_find_protocol_name(oc->url);
@@ -2484,6 +2543,8 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
if (hls->flags & HLS_SINGLE_FILE) {
vs->start_pos += vs->size;
+ if (hls->key_info_file || hls->encrypt)
+ ret = hls_start(s, vs);
} else if (hls->max_seg_size > 0) {
if (vs->size + vs->start_pos >= hls->max_seg_size) {
vs->sequence++;
@@ -2644,7 +2705,12 @@ static int hls_write_trailer(struct AVFormatContext *s)
if (ret < 0)
av_log(s, AV_LOG_WARNING, "Failed to upload file '%s' at the end.\n", oc->url);
}
-
+ if (hls->flags & HLS_SINGLE_FILE) {
+ if (hls->key_info_file || hls->encrypt) {
+ vs->size = append_single_file(s, vs);
+ }
+ hlsenc_io_close(s, &vs->out_single_file, vs->basename);
+ }
failed:
av_freep(&vs->temp_buffer);
av_dict_free(&options);