avformat/mux_utils: Move ff_format_shift_data to new file for mux utils

It is only used by muxers. Given that it is not part of
the core muxing code and given that mux.c is already big enough,
it is moved to a new file for utility functions for muxing.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt 2022-05-06 15:43:55 +02:00
parent b9f6d416ec
commit ba49acf143
6 changed files with 90 additions and 64 deletions

View File

@ -17,6 +17,7 @@ OBJS = allformats.o \
isom_tags.o \
metadata.o \
mux.o \
mux_utils.o \
options.o \
os_support.o \
protocols.o \

View File

@ -946,13 +946,6 @@ void ff_format_set_url(AVFormatContext *s, char *url);
void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]);
/**
* Make shift_size amount of space at read_start by shifting data in the output
* at read_start until the current IO position. The underlying IO context must
* be seekable.
*/
int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size);
/**
* Rescales a timestamp and the endpoints of an interval to which the temstamp
* belongs, from a timebase `tb_in` to a timebase `tb_out`.

View File

@ -96,4 +96,11 @@ enum AVWriteUncodedFrameFlags {
};
/**
* Make shift_size amount of space at read_start by shifting data in the output
* at read_start until the current IO position. The underlying IO context must
* be seekable.
*/
int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size);
#endif /* AVFORMAT_MUX_H */

81
libavformat/mux_utils.c Normal file
View File

@ -0,0 +1,81 @@
/*
* Various muxing utility functions
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
#include "avio.h"
#include "internal.h"
#include "mux.h"
int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size)
{
int ret;
int64_t pos, pos_end;
uint8_t *buf, *read_buf[2];
int read_buf_id = 0;
int read_size[2];
AVIOContext *read_pb;
buf = av_malloc_array(shift_size, 2);
if (!buf)
return AVERROR(ENOMEM);
read_buf[0] = buf;
read_buf[1] = buf + shift_size;
/* Shift the data: the AVIO context of the output can only be used for
* writing, so we re-open the same output, but for reading. It also avoids
* a read/seek/write/seek back and forth. */
avio_flush(s->pb);
ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL);
if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url);
goto end;
}
/* mark the end of the shift to up to the last data we wrote, and get ready
* for writing */
pos_end = avio_tell(s->pb);
avio_seek(s->pb, read_start + shift_size, SEEK_SET);
avio_seek(read_pb, read_start, SEEK_SET);
pos = avio_tell(read_pb);
#define READ_BLOCK do { \
read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size); \
read_buf_id ^= 1; \
} while (0)
/* shift data by chunk of at most shift_size */
READ_BLOCK;
do {
int n;
READ_BLOCK;
n = read_size[read_buf_id];
if (n <= 0)
break;
avio_write(s->pb, read_buf[read_buf_id], n);
pos += n;
} while (pos < pos_end);
ret = ff_format_io_close(s, &read_pb);
end:
av_free(buf);
return ret;
}

View File

@ -33,8 +33,8 @@
#include "libavutil/intreadwrite.h"
#include "libavcodec/bytestream.h"
#include "avformat.h"
#include "internal.h"
#include "avio_internal.h"
#include "mux.h"
typedef struct FILMOutputContext {
AVIOContext *header;

View File

@ -1832,59 +1832,3 @@ void ff_format_set_url(AVFormatContext *s, char *url)
av_freep(&s->url);
s->url = url;
}
int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size)
{
int ret;
int64_t pos, pos_end;
uint8_t *buf, *read_buf[2];
int read_buf_id = 0;
int read_size[2];
AVIOContext *read_pb;
buf = av_malloc_array(shift_size, 2);
if (!buf)
return AVERROR(ENOMEM);
read_buf[0] = buf;
read_buf[1] = buf + shift_size;
/* Shift the data: the AVIO context of the output can only be used for
* writing, so we re-open the same output, but for reading. It also avoids
* a read/seek/write/seek back and forth. */
avio_flush(s->pb);
ret = s->io_open(s, &read_pb, s->url, AVIO_FLAG_READ, NULL);
if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url);
goto end;
}
/* mark the end of the shift to up to the last data we wrote, and get ready
* for writing */
pos_end = avio_tell(s->pb);
avio_seek(s->pb, read_start + shift_size, SEEK_SET);
avio_seek(read_pb, read_start, SEEK_SET);
pos = avio_tell(read_pb);
#define READ_BLOCK do { \
read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], shift_size); \
read_buf_id ^= 1; \
} while (0)
/* shift data by chunk of at most shift_size */
READ_BLOCK;
do {
int n;
READ_BLOCK;
n = read_size[read_buf_id];
if (n <= 0)
break;
avio_write(s->pb, read_buf[read_buf_id], n);
pos += n;
} while (pos < pos_end);
ret = ff_format_io_close(s, &read_pb);
end:
av_free(buf);
return ret;
}