From patchwork Sat Jul 18 00:19:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 21160 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a25:80ca:0:0:0:0:0 with SMTP id c10csp42995ybm; Fri, 17 Jul 2020 17:21:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxLum+TVLNuji6LhXVhKgX35TMjo7X208tjcTUzLTd8aaJEpzjfo7V+iU13Y5w0GCLG62Ml X-Received: by 2002:a1c:4185:: with SMTP id o127mr11413153wma.8.1595031668967; Fri, 17 Jul 2020 17:21:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1595031668; cv=none; d=google.com; s=arc-20160816; b=U+mq8HUU5NwkuBXEbcpUZLnlr4k1470JzN78H8YBSTCmjCIUcMaLJfsFPAkuxfpqRF uE2c52BPtf3UD0w/47wF3XCSC30i1tKhAD09y/NayC5odQAcEy6rYPTBy0QnA/bDoZU2 IEevMd77xtA8MEN4vQ57UPbIqbd5IQOL6C+nbDjtpxM0wbbRKzPxmJhu5HVc5SnIE9Sw SJAyH/YDcDIO+4xDsc/uqgrP2g1owLPOkNCi0lOmqnZMbZZfo24MXe7JUNGAkOaahy65 xBxE5jy5frQii5AM7gpUfbAfBbBQ6VK26r0mvUGiTFiLpLnXfjVD7tWHK8KUMam7OSdV FgeQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=zvJiCZhQTB2Y5+ds3IXydonOEGuLzsQkdlTv4GQhSQk=; b=gAfoqBQGockN3g7JTddJ1AxcE+392PwZLyJ1OcwQXH0EYRpI4JV0AvySUu6ZQVeDeT FeMiVyCYlDprIUYBU5gfIo0Y1NtzFRcscTmPPV5LMt6JvNTmBnmM5ekD2j6b4hW8gMdd cQDW23rbS3B3yfByTb3I5CV8ZtHSBVX9qrjHI9Nf8x028aIzuP/Z/1OhsESyh6FoLNGe tUXKuu0iK3syLKWiQ5vDF8Rf/XhlT++TcfFcw2EBPxDupEOnh9nlDgmysvBBB+46i/CA sq3is0t27L+Hv117ZBwG6QPihP7C4nNqd3V8Zd8OtAVHJ6tYj6T4WaBDTsIatg1ErX5Q MxOw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=FK8bqkIO; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id h9si9204455wml.155.2020.07.17.17.21.08; Fri, 17 Jul 2020 17:21:08 -0700 (PDT) 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; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=FK8bqkIO; 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; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 2102968B6C2; Sat, 18 Jul 2020 03:20:05 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8791568B6F5 for ; Sat, 18 Jul 2020 03:19:57 +0300 (EEST) Received: by mail-ed1-f47.google.com with SMTP id a8so9043837edy.1 for ; Fri, 17 Jul 2020 17:19:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KdP52qx6A0bQYd8MLhyn9wvXr4GdWijiH/qDXEmDQpk=; b=FK8bqkIONO0K7dp5wtadiKfW3FpB/gzEznowVc/7FGH4Kig3q51GpKx0GgsT9Q/rym InbuzMpyYtA7Cs1igHew0KGpAdc0GqtqlybdAOFbXPEhFXITdjyOYm1qf8AiWJtwMy+S RgASTcnc3YfPQDTDEu6DKeKFqU9u44Afhwq7DdPHICUFhq+qjFH1BXLIrPHNEQnGtYTO hcEv3mTqkDx3/92Rd2LZmL/N1WqbFtyzuFbyrvNSeovaEJDNkYO7Rwh7bxKGzxeWO9nm +xBfnn1Z5TiKUE5AguYyfHyyeuURoSg9Uobuc+USRgA1euzItxy6hgUIdy8F/rg6k9FJ BTpQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KdP52qx6A0bQYd8MLhyn9wvXr4GdWijiH/qDXEmDQpk=; b=gucenLJy+h3VoumXo4Y2kPPCAaqxCR31SjRVrHV+gofD4ip2zb5LxpAL5ArzrDSS9e 30J1qQAFkhhTqv7ILpXK70NhE4GZKhLYMLVKTo9ukScVu8kKSxsdFDe9lasdBZPyV2TE wi5xI8RiWKGJ2eIr7m4d1HQwne7hwfTTZfCWYle0a747NsNSr38cOLtuDFe26FyHQ31E DzLnESULF19hyYAAg3Pii8IcwxbcPntp1BgTto4jhf0jVc8qoWC1bjE/X22g6nr006T+ FPWW2kqJSFxvbnH7GXpbLWACgdi4nCI+R6YKFZcZUTONDKOwrC6w6meJDku+J0U3mLIk EC3g== X-Gm-Message-State: AOAM531RkPMlI7Af/ISUy3KOisJbzUM2AvJ0RKlax4xp6TtCcw0YnJZp s9UaoEfBiI6Eqtt8IBiwVsyhtinr X-Received: by 2002:a50:f392:: with SMTP id g18mr11476688edm.151.1595031596590; Fri, 17 Jul 2020 17:19:56 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc10296.dynamic.kabel-deutschland.de. [188.193.2.150]) by smtp.gmail.com with ESMTPSA id y7sm9299001ejd.73.2020.07.17.17.19.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jul 2020 17:19:56 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 18 Jul 2020 02:19:27 +0200 Message-Id: <20200718001928.10603-9-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200718000636.2167-1-andreas.rheinhardt@gmail.com> References: <20200718000636.2167-1-andreas.rheinhardt@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 10/11] avformat/segafilmenc: Don't store packet info in linked list 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: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: KIibsHB6jiUX Content-Length: 11810 Up until now, the Sega FILM muxer would store some information about each packet in a linked list. When writing the trailer, the information in said linked list would be used to write a table in the file header. Each entry in said table is 16 bytes long, but each entry of the linked list is 32 bytes long (assuming 64 bit pointer and no padding). Therefore it makes sense to remove the linked list and write the array entries directly into a dynamic buffer while writing the packet (this is possible because the table entries don't depend on any information not available when writing the packet (the offset is not relative to the beginning of the file, but to the end of the table). This also simplifies writing the array at the end (there is no need to traverse a linked list). Signed-off-by: Andreas Rheinhardt --- libavformat/segafilmenc.c | 129 ++++++++++++-------------------------- 1 file changed, 40 insertions(+), 89 deletions(-) diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index d935caf00d..11ed279a05 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -34,81 +34,21 @@ #include "internal.h" #include "avio_internal.h" -typedef struct FILMPacket { - int audio; - int keyframe; - int32_t pts; - int32_t duration; - int32_t size; - int32_t index; - struct FILMPacket *next; -} FILMPacket; - typedef struct FILMOutputContext { + AVIOContext *header; + unsigned index; int audio_index; int video_index; - FILMPacket *start; - FILMPacket *last; - int64_t packet_count; } FILMOutputContext; -static int film_write_packet_to_header(AVFormatContext *format_context, FILMPacket *pkt) -{ - AVIOContext *pb = format_context->pb; - /* The bits in these two 32-bit integers contain info about the contents of this sample */ - int32_t info1 = 0; - int32_t info2 = 0; - - if (pkt->audio) { - /* Always the same, carries no more information than "this is audio" */ - info1 = 0xFFFFFFFF; - info2 = 1; - } else { - info1 = pkt->pts; - info2 = pkt->duration; - /* The top bit being set indicates a key frame */ - if (!pkt->keyframe) - info1 |= 1U << 31; - } - - /* Write the 16-byte sample info packet to the STAB chunk in the header */ - avio_wb32(pb, pkt->index); - avio_wb32(pb, pkt->size); - avio_wb32(pb, info1); - avio_wb32(pb, info2); - - return 0; -} - static int film_write_packet(AVFormatContext *format_context, AVPacket *pkt) { - FILMPacket *metadata; AVIOContext *pb = format_context->pb; FILMOutputContext *film = format_context->priv_data; - int encoded_buf_size = 0; + int encoded_buf_size, size = pkt->size; + uint32_t info1, info2; enum AVCodecID codec_id; - /* Track the metadata used to write the header and add it to the linked list */ - metadata = av_mallocz(sizeof(FILMPacket)); - if (!metadata) - return AVERROR(ENOMEM); - metadata->audio = pkt->stream_index == film->audio_index; - metadata->keyframe = pkt->flags & AV_PKT_FLAG_KEY; - metadata->pts = pkt->pts; - metadata->duration = pkt->duration; - metadata->size = pkt->size; - if (film->last == NULL) { - metadata->index = 0; - } else { - metadata->index = film->last->index + film->last->size; - film->last->next = metadata; - } - metadata->next = NULL; - if (film->start == NULL) - film->start = metadata; - film->packet_count++; - film->last = metadata; - codec_id = format_context->streams[pkt->stream_index]->codecpar->codec_id; /* Sega Cinepak has an extra two-byte header; write dummy data there, @@ -123,7 +63,7 @@ static int film_write_packet(AVFormatContext *format_context, AVPacket *pkt) * 8 bytes too short. However, the size in the STAB section of the header * is correct, taking into account the extra two bytes. */ AV_WB24(&pkt->data[1], pkt->size - 8 + 2); - metadata->size += 2; + size += 2; avio_write(pb, pkt->data, 10); avio_wb16(pb, 0); @@ -134,7 +74,27 @@ static int film_write_packet(AVFormatContext *format_context, AVPacket *pkt) avio_write(pb, pkt->data, pkt->size); } - return 0; + /* Add the 16-byte sample info entry to the dynamic buffer + * for the STAB chunk in the header */ + pb = film->header; + avio_wb32(pb, film->index); + film->index += size; + avio_wb32(pb, size); + if (film->audio_index == pkt->stream_index) { + /* Always the same, carries no more information than "this is audio" */ + info1 = 0xFFFFFFFF; + info2 = 1; + } else { + info1 = pkt->pts; + info2 = pkt->duration; + /* The top bit being set indicates a key frame */ + if (!(pkt->flags & AV_PKT_FLAG_KEY)) + info1 |= 1U << 31; + } + avio_wb32(pb, info1); + avio_wb32(pb, info2); + + return pb->error; } static int get_audio_codec_id(enum AVCodecID codec_id) @@ -154,11 +114,10 @@ static int get_audio_codec_id(enum AVCodecID codec_id) static int film_init(AVFormatContext *format_context) { FILMOutputContext *film = format_context->priv_data; + int ret; + film->audio_index = -1; film->video_index = -1; - film->packet_count = 0; - film->start = NULL; - film->last = NULL; for (int i = 0; i < format_context->nb_streams; i++) { AVStream *st = format_context->streams[i]; @@ -199,6 +158,8 @@ static int film_init(AVFormatContext *format_context) av_log(format_context, AV_LOG_ERROR, "No video stream present.\n"); return AVERROR(EINVAL); } + if ((ret = avio_open_dyn_buf(&film->header)) < 0) + return ret; return 0; } @@ -263,15 +224,17 @@ static int shift_data(AVFormatContext *format_context, int64_t shift_size) static int film_write_header(AVFormatContext *format_context) { int ret = 0; - int64_t sample_table_size, stabsize, headersize; + unsigned sample_table_size, stabsize, headersize, packet_count; AVIOContext *pb = format_context->pb; FILMOutputContext *film = format_context->priv_data; - FILMPacket *prev, *packet; AVStream *video = NULL; + uint8_t *sample_table; /* Calculate how much we need to reserve for the header; * this is the amount the rest of the data will be shifted up by. */ - sample_table_size = film->packet_count * 16; + sample_table_size = avio_get_dyn_buf(film->header, &sample_table); + packet_count = sample_table_size / 16; + sample_table_size = packet_count * 16; stabsize = 16 + sample_table_size; headersize = 16 + /* FILM header base */ 32 + /* FDSC chunk */ @@ -335,7 +298,7 @@ static int film_write_header(AVFormatContext *format_context) /* Finally, write the STAB (sample table) chunk */ ffio_wfourcc(pb, "STAB"); - avio_wb32(pb, 16 + (film->packet_count * 16)); + avio_wb32(pb, stabsize); /* Framerate base frequency. Here we're assuming that the frame rate is even. * In real world Sega FILM files, there are usually a couple of approaches: * a) framerate base frequency is the same as the framerate, and ticks @@ -347,17 +310,10 @@ static int film_write_header(AVFormatContext *format_context) * are incremented by 25 for an evenly spaced framerate of 24fps. */ avio_wb32(pb, av_q2d(av_inv_q(video->time_base))); - avio_wb32(pb, film->packet_count); + avio_wb32(pb, packet_count); /* Finally, write out each packet's data to the header */ - packet = film->start; - while (packet != NULL) { - film_write_packet_to_header(format_context, packet); - prev = packet; - packet = packet->next; - av_freep(&prev); - } - film->start = film->last = NULL; + avio_write(pb, sample_table, sample_table_size); return 0; } @@ -365,13 +321,8 @@ static int film_write_header(AVFormatContext *format_context) static void film_deinit(AVFormatContext *format_context) { FILMOutputContext *film = format_context->priv_data; - FILMPacket *packet = film->start; - while (packet != NULL) { - FILMPacket *next = packet->next; - av_free(packet); - packet = next; - } - film->start = film->last = NULL; + + ffio_free_dyn_buf(&film->header); } AVOutputFormat ff_segafilm_muxer = {