From patchwork Sun Dec 3 14:54:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rainer Hochecker X-Patchwork-Id: 6526 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.94 with SMTP id m30csp3398260jah; Sun, 3 Dec 2017 06:55:00 -0800 (PST) X-Google-Smtp-Source: AGs4zMbRtQE5COED6x2wsAoOOddmkMieWfTS1ht2M0TbG3WynXIWVUaXaYkkV/Q3uvLxgWsImrGQ X-Received: by 10.28.67.2 with SMTP id q2mr4949462wma.38.1512312900826; Sun, 03 Dec 2017 06:55:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512312900; cv=none; d=google.com; s=arc-20160816; b=JSPoRsgnT0kBfKXeFnjpKaH8+M5SJA/6rFaewUbxzUIap2uVC+V6ICjgA4F6rZMvh4 HJ9lJBwQZiM9YknDQz0yK4JYmsyJdNydWFD99Pn+ofhcv7YPVl9aEkZzkrDOnNLy67kP 8JwkLMuMR6j3Zv6tqqLI/NXzgRFi1+jFG+FitMwSiNMgym6askY5TlLz2DnDunEL8YXL kyjuUsYR8b47WsS8OTmWvqS/X93s5Lu44Z214sZqiyg7poDdT8Qy7A3jejLnIVa0Ql0u 57xn5p4RSrr+5cGzVwuZSkTR8ZSxR/pDQRnKYkIxi02MhsK24PaZbeFQSqxcfCQ3kPS3 CnqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:delivered-to:arc-authentication-results; bh=B1vh91NBrKhqC8FlEiVtfi3RpYl3MxVcmY7fy/tI87I=; b=XzJMsO8z5Vf/5CNmjXRaQXa+6M5xyFCv2HqqU7BM9Kkf8JkD4Mu8B/0pXSJhXj8F/w 6e5Ai1ujg97AENoz4rsoTiUDR7wU19Ej4PNKmSjH39WDBMrDf3r5D0VHj90NaSIPLcZc okhCWTVeRnVrJp5hruio9s7xOffA6xv4Ds8K18ycxzFMhsf508m8jksWIp7qO2tLtMEL 0RMUZwPhsBY83vWhvXp+jOxeeofKpAb0G7QjFZHkC6fzOfdBhm9EDQxg36MBdVF9whqS j0XNEZE6A7fAHXJMK8t2KCLM7tMFnkMo8SQxVbyDWFQNow6n21FsHUF2IjGm2PxAnbGr Nuxg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o70si3706127wmi.78.2017.12.03.06.55.00; Sun, 03 Dec 2017 06:55:00 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9529568A547; Sun, 3 Dec 2017 16:54:49 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout.kundenserver.de (mout.kundenserver.de [212.227.17.13]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9580268A501 for ; Sun, 3 Dec 2017 16:54:43 +0200 (EET) Received: from localhost.localdomain ([89.247.207.216]) by mrelayeu.kundenserver.de (mreue105 [212.227.15.183]) with ESMTPSA (Nemesis) id 0Le53E-1erZkX11BM-00ptfE; Sun, 03 Dec 2017 15:54:45 +0100 From: Rainer Hochecker To: ffmpeg-devel@ffmpeg.org Date: Sun, 3 Dec 2017 15:54:35 +0100 Message-Id: <20171203145436.42095-2-fernetmenta@online.de> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171203145436.42095-1-fernetmenta@online.de> References: <0489f119587681fc5a2b15fdc8afdd2d@mail.onse.fi> <20171203145436.42095-1-fernetmenta@online.de> X-Provags-ID: V03:K0:kmcsWKpFf9WXdnk8lM9rQE1H9olYhuCaLJWRkrYhPuo37dYe/VK buQ1Trcvs12YcT7X8tc+tMgBRhyxjCm4/UyQLYY1xgRQpt/1VYYeBLbn33kTMCEF/Em8SxV 9dMvCHe9OjKbzl8IXsI/8A477aVJtIaKqTUKU78StirTV5cM1hUaZSaKea/1LCmx1PL25uK nfNaDu2OhJEPyTzUBdUIA== X-UI-Out-Filterresults: notjunk:1; V01:K0:k4ajUffbklc=:nGdyOcHvROqdHBoViLoLv3 nyAD9ZA1A3AqFgfUPEyO/OqiPmEWNxtyKjmoSLHnzAZ8RLZJTn+Jf1GjSHMZqWNbmsm5UkUJd go/tT9NbBJrUID80OeoN4I1WRy1wDkFIPMhpCCfoJQOC8x3ehUn0ctu6rMPxl+TrBsq6uyFCE k/hSWnwMPYepGAfaWFd+NWGzum8dGrXAHGlwSM62mEPhviPjVwOX5twW4O+TW14Q3qxJwMkgy IMjMNMhtpaPN18I1cWk2Rpc3cE5N1fk0Fe2KQPDFPkEiwtDS8WQgI2EuT7Ih4Al/QJZIn+EgY TU0xZY8J1SXQ3gg5ZISnsj2rkppPvsasLLEpaDG3hPnOW3xFIIXuHiNZAQOrF2yFlc1StIEWi VFO3iVpSjZfL5TPguz+otoDEEo+LwM57EAPCaPw0xminV+YNelxt+3u80Jjjgd8ATq1S0UKp2 dvtXgAsv5TTGWwF2CdrkVxgAHVhikP+CurBSCNelW6fGoLzy/WpqmOVr1Kb6P7Wbgwtm3RTBr TiqcBMBADXwZ8Vx5YM3GKOWTOhZ/baOVNnEHyZbTKe6K/X/mMOpamlsdVBjd4BQaMLBLwveVz W4u+o6hXBe+OIdKPvcocXZLLtW8Ufw0rk8uk5pTBzON2XH6d8imJwMAJcFGsxj/4mBUYDbJFn TjL+0s851GvzTbCbxNAB8GW89PWcxX/fRKNjD9wXMHawK8NCwnQqOMOTyw1FTO/gliSwliRap d7xP0D/nZClDnnmlTmz1NCDSCd/5q0W3nsJiXg== Subject: [FFmpeg-devel] [PATCH v4 1/2] lavf/hls: refactoring of read_header 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: Rainer Hochecker MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" --- libavformat/hls.c | 208 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 119 insertions(+), 89 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index ab6ff187a6..3c2c720abe 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -314,6 +314,8 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->is_id3_timestamped = -1; pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; + pls->index = c->n_playlists; + pls->needed = 0; dynarray_add(&c->playlists, &c->n_playlists, pls); return pls; } @@ -1670,6 +1672,121 @@ static int hls_close(AVFormatContext *s) return 0; } +static int init_playlist(HLSContext *c, struct playlist *pls) +{ + AVInputFormat *in_fmt = NULL; + int highest_cur_seq_no = 0; + int ret; + int i; + + if (!(pls->ctx = avformat_alloc_context())) { + return AVERROR(ENOMEM); + } + + if (pls->n_segments == 0) + return 0; + + pls->needed = 1; + pls->parent = c->ctx; + + /* + * If this is a live stream and this playlist looks like it is one segment + * behind, try to sync it up so that every substream starts at the same + * time position (so e.g. avformat_find_stream_info() will see packets from + * all active streams within the first few seconds). This is not very generic, + * though, as the sequence numbers are technically independent. + */ + highest_cur_seq_no = 0; + for (i = 0; i < c->n_playlists; i++) { + struct playlist *pls = c->playlists[i]; + if (pls->cur_seq_no > highest_cur_seq_no) + highest_cur_seq_no = pls->cur_seq_no; + } + if (!pls->finished && pls->cur_seq_no == highest_cur_seq_no - 1 && + highest_cur_seq_no < pls->start_seq_no + pls->n_segments) { + pls->cur_seq_no = highest_cur_seq_no; + } + + pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE); + if (!pls->read_buffer){ + ret = AVERROR(ENOMEM); + avformat_free_context(pls->ctx); + pls->ctx = NULL; + return ret; + } + ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls, + read_data, NULL, NULL); + pls->pb.seekable = 0; + ret = av_probe_input_buffer(&pls->pb, &in_fmt, pls->segments[0]->url, + NULL, 0, 0); + if (ret < 0) { + /* Free the ctx - it isn't initialized properly at this point, + * so avformat_close_input shouldn't be called. If + * avformat_open_input fails below, it frees and zeros the + * context, so it doesn't need any special treatment like this. */ + av_log(c->ctx, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url); + avio_closep(&pls->pb); + avformat_free_context(pls->ctx); + pls->ctx = NULL; + return ret; + } + pls->ctx->pb = &pls->pb; + pls->ctx->io_open = nested_io_open; + pls->ctx->flags |= c->ctx->flags & ~AVFMT_FLAG_CUSTOM_IO; + + if ((ret = ff_copy_whiteblacklists(pls->ctx, c->ctx)) < 0) + return ret; + + ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL); + if (ret < 0) { + av_log(c->ctx, AV_LOG_ERROR, "Error opening playlist %s", pls->segments[0]->url); + avformat_free_context(pls->ctx); + pls->ctx = NULL; + return ret; + } + + if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { + ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra); + avformat_queue_attached_pictures(pls->ctx); + ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); + pls->id3_deferred_extra = NULL; + } + + if (pls->is_id3_timestamped == -1) + av_log(c->ctx, AV_LOG_WARNING, "No expected HTTP requests have been made\n"); + + /* + * For ID3 timestamped raw audio streams we need to detect the packet + * durations to calculate timestamps in fill_timing_for_id3_timestamped_stream(), + * but for other streams we can rely on our user calling avformat_find_stream_info() + * on us if they want to. + */ + if (pls->is_id3_timestamped) { + ret = avformat_find_stream_info(pls->ctx, NULL); + if (ret < 0) { + avformat_free_context(pls->ctx); + pls->ctx = NULL; + return ret; + } + } + + pls->has_noheader_flag = !!(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER); + + /* Create new AVStreams for each stream in this playlist */ + ret = update_streams_from_subdemuxer(c->ctx, pls); + if (ret < 0) { + avformat_free_context(pls->ctx); + pls->ctx = NULL; + return ret; + } + + add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_AUDIO); + add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_VIDEO); + add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_SUBTITLE); + + return 0; +} + static int hls_read_header(AVFormatContext *s) { void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb; @@ -1775,97 +1892,10 @@ static int hls_read_header(AVFormatContext *s) /* Open the demuxer for each playlist */ for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; - AVInputFormat *in_fmt = NULL; - - if (!(pls->ctx = avformat_alloc_context())) { - ret = AVERROR(ENOMEM); - goto fail; - } - - if (pls->n_segments == 0) - continue; - pls->index = i; - pls->needed = 1; - pls->parent = s; - - /* - * If this is a live stream and this playlist looks like it is one segment - * behind, try to sync it up so that every substream starts at the same - * time position (so e.g. avformat_find_stream_info() will see packets from - * all active streams within the first few seconds). This is not very generic, - * though, as the sequence numbers are technically independent. - */ - if (!pls->finished && pls->cur_seq_no == highest_cur_seq_no - 1 && - highest_cur_seq_no < pls->start_seq_no + pls->n_segments) { - pls->cur_seq_no = highest_cur_seq_no; - } - - pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE); - if (!pls->read_buffer){ - ret = AVERROR(ENOMEM); - avformat_free_context(pls->ctx); - pls->ctx = NULL; - goto fail; - } - ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls, - read_data, NULL, NULL); - pls->pb.seekable = 0; - ret = av_probe_input_buffer(&pls->pb, &in_fmt, pls->segments[0]->url, - NULL, 0, 0); - if (ret < 0) { - /* Free the ctx - it isn't initialized properly at this point, - * so avformat_close_input shouldn't be called. If - * avformat_open_input fails below, it frees and zeros the - * context, so it doesn't need any special treatment like this. */ - av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url); - avformat_free_context(pls->ctx); - pls->ctx = NULL; - goto fail; - } - pls->ctx->pb = &pls->pb; - pls->ctx->io_open = nested_io_open; - pls->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO; - - if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0) - goto fail; - - ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL); - if (ret < 0) - goto fail; - - if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { - ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra); - avformat_queue_attached_pictures(pls->ctx); - ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); - pls->id3_deferred_extra = NULL; - } - - if (pls->is_id3_timestamped == -1) - av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n"); - - /* - * For ID3 timestamped raw audio streams we need to detect the packet - * durations to calculate timestamps in fill_timing_for_id3_timestamped_stream(), - * but for other streams we can rely on our user calling avformat_find_stream_info() - * on us if they want to. - */ - if (pls->is_id3_timestamped) { - ret = avformat_find_stream_info(pls->ctx, NULL); - if (ret < 0) - goto fail; - } - - pls->has_noheader_flag = !!(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER); - - /* Create new AVStreams for each stream in this playlist */ - ret = update_streams_from_subdemuxer(s, pls); - if (ret < 0) - goto fail; + if ((ret = init_playlist(c, pls)) < 0) + goto fail; - add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO); - add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO); - add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE); } update_noheader_flag(s);