From patchwork Wed Jul 22 08:11:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liu Steven X-Patchwork-Id: 21220 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id F377844A207 for ; Wed, 22 Jul 2020 11:11:48 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D630668B793; Wed, 22 Jul 2020 11:11:48 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtpproxy21.qq.com (smtpbg702.qq.com [203.205.195.102]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3B44B68B7A4 for ; Wed, 22 Jul 2020 11:11:46 +0300 (EEST) X-QQ-mid: bizesmtp23t1595405481tia27w4f Received: from localhost (unknown [103.107.216.230]) by esmtp10.qq.com (ESMTP) with id ; Wed, 22 Jul 2020 16:11:20 +0800 (CST) X-QQ-SSF: 01100000002000Z0ZXF0B00A0000000 X-QQ-FEAT: uPKj8ga2w7H8ckcsg9q72BCJzeaXUw8HALruLPhczsL9kHDRvhR765jT7bejZ vpruMdxJdK8jNu8nrGxPju9hOzvrL2KNyKxOU1CLdtesSkDa0+89Hs9hlXfFa61Ba4snXSB rKO5OgN7UiVOVrTKhy3zZ/MEJaftk71aYX5WWXcTGQTdSMdWy4DqLqgr76F3WYZUZE2kG1L 3b0wwaRzE25Ez1ZBMAd1IDEwYFfl7RfuEGtbLJzTdrOJeL+SuYeWObT1yT10a8IUCAGjXoE ZBQJJDjONonRgWXLmX4WWS9EeFJJ56aU7r6HcMvfIQ/wRDpSLxI+NkryKAKb2ChGh0EQ== X-QQ-GoodBg: 0 From: Steven Liu To: ffmpeg-devel@ffmpeg.org Date: Wed, 22 Jul 2020 16:11:03 +0800 Message-Id: <20200722081103.69962-2-lq@chinaffmpeg.org> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200722081103.69962-1-lq@chinaffmpeg.org> References: <20200722081103.69962-1-lq@chinaffmpeg.org> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:chinaffmpeg.org:qybgforeign:qybgforeign7 X-QQ-Bgrelay: 1 Subject: [FFmpeg-devel] [PATCH 2/2] avformat/hlsenc: write temp file for append single file by encryption mode X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Steven Liu Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" fix ticket: 8783 Because in single file by encryption mode, it cannot get the last one block of the file, it need ff_format_io_close for get full file size, then hlsenc can get the total size of the encryption content, so write the content into temp file first, and get the temp file content append the temp file content into append to single file, then hlsenc can get the correct file/content size and offset. Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 70 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index df84e6487d..0b859ae579 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); + ret = hlsenc_io_close(s, &vs->out_single_file, vs->basename); + } + } failed: av_freep(&vs->temp_buffer); av_dict_free(&options);