Compare commits

...

10 Commits

Author SHA1 Message Date
vectronic
7f51cf75c6 avformat/hls: improve comment
Signed-off-by: vectronic <hello.vectronic@gmail.com>
2024-11-10 11:20:08 +08:00
vectronic
380a518c43 avformat/mov: if pos has been reset, clear fragments and indexes and search for next root
fixes https://trac.ffmpeg.org/ticket/7359

Signed-off-by: vectronic <hello.vectronic@gmail.com>
2024-11-10 11:20:01 +08:00
Peter Ross
2f34b159b4 avcodec/eatgq: decode motion vector macroblocks
Signed-off-by: Peter Ross <pross@xvid.org>
2024-11-10 12:31:19 +11:00
James Almer
10c02deccb avfilter/vf_zscale: extend the configuration log message with color space info
And print it in DEBUG level, not TRACE, as it's useful information.

Signed-off-by: James Almer <jamrial@gmail.com>
2024-11-09 19:33:57 -03:00
James Almer
5c8268ac56 avfilter/vf_zscale: remove unecessary argument from realign_frame
Possible since the previous commit.

Signed-off-by: James Almer <jamrial@gmail.com>
2024-11-09 19:33:56 -03:00
James Almer
c8e5c684b3 avfilter/vf_zscale: align the frame buffers
Signed-off-by: James Almer <jamrial@gmail.com>
2024-11-09 19:33:56 -03:00
Pavel Koshevoy
00cf3df03f lavfi/vf_zscale: fix call to av_pix_fmt_count_planes
realign_frame called av_pix_fmt_count_planes with incorrect parameter.

Signed-off-by: James Almer <jamrial@gmail.com>
2024-11-09 19:33:56 -03:00
Pavel Koshevoy
7b302f4db7 lavfi/vf_zscale: fix tmp buffer ptr alignment for zimg_filter_graph_process
Signed-off-by: James Almer <jamrial@gmail.com>
2024-11-09 19:33:56 -03:00
James Almer
f15fc27db5 avfilter/framepool: align the frame buffers
And not just the linesizes. Use the extra align bytes allocated for this purpose.

Signed-off-by: James Almer <jamrial@gmail.com>
2024-11-09 19:33:56 -03:00
Marth64
6d5a0998b6 doc/bitstream_filters: elaborate on h264_redundant_pps
Signed-off-by: Marth64 <marth64@proxyid.net>
2024-11-09 10:02:34 -06:00
7 changed files with 133 additions and 40 deletions

View File

@ -423,9 +423,21 @@ Please note that this filter is auto-inserted for MPEG-TS (muxer
@section h264_redundant_pps
This applies a specific fixup to some Blu-ray streams which contain
redundant PPSs modifying irrelevant parameters of the stream which
confuse other transformations which require correct extradata.
This applies a specific fixup to some Blu-ray BDMV H264 streams
which contain redundant PPSs. The PPSs modify irrelevant parameters
of the stream, confusing other transformations which require
the correct extradata.
The encoder used on these impacted streams adds extra PPSs throughout
the stream, varying the initial QP and whether weighted prediction
was enabled. This causes issues after copying the stream into
a global header container, as the starting PPS is not suitable
for the rest of the stream. One side effect, for example,
is seeking will return garbled output until a new PPS appears.
This BSF removes the extra PPSs and rewrites the slice headers
such that the stream uses a single leading PPS in the global header,
which resolves the issue.
@section hevc_metadata

View File

@ -905,7 +905,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
.type = AVMEDIA_TYPE_VIDEO,
.name = "tgq",
.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
.props = AV_CODEC_PROP_LOSSY,
},
{
.id = AV_CODEC_ID_TQI,

View File

@ -36,12 +36,14 @@
#include "avcodec.h"
#include "bytestream.h"
#include "codec_internal.h"
#include "copy_block.h"
#include "decode.h"
#include "eaidct.h"
#include "get_bits.h"
typedef struct TgqContext {
AVCodecContext *avctx;
AVFrame *last_frame;
int width, height;
int qtable[64];
DECLARE_ALIGNED(16, int16_t, block)[6][64];
@ -53,6 +55,9 @@ static av_cold int tgq_decode_init(AVCodecContext *avctx)
s->avctx = avctx;
avctx->framerate = (AVRational){ 15, 1 };
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
s->last_frame = av_frame_alloc();
if (!s->last_frame)
return AVERROR(ENOMEM);
return 0;
}
@ -173,7 +178,33 @@ static int tgq_decode_mb(TgqContext *s, GetByteContext *gbyte,
tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);
bytestream2_skip(gbyte, mode);
} else {
if (mode == 3) {
if (mode == 1) {
int x, y;
int mv = bytestream2_get_byte(gbyte);
int mv_x = mv >> 4;
int mv_y = mv & 0x0F;
if (!s->last_frame->data[0]) {
av_log(s->avctx, AV_LOG_ERROR, "missing reference frame\n");
return -1;
}
if (mv_x >= 8) mv_x -= 16;
if (mv_y >= 8) mv_y -= 16;
x = mb_x * 16 - mv_x;
y = mb_y * 16 - mv_y;
if (x < 0 || x + 16 > s->width || y < 0 || y + 16 > s->height) {
av_log(s->avctx, AV_LOG_ERROR, "invalid motion vector\n");
return -1;
}
copy_block16(frame->data[0] + (mb_y * 16 * frame->linesize[0]) + mb_x * 16,
s->last_frame->data[0] + y * s->last_frame->linesize[0] + x,
frame->linesize[0], s->last_frame->linesize[0], 16);
for (int p = 1; p < 3; p++)
copy_block8(frame->data[p] + (mb_y * 8 * frame->linesize[p]) + mb_x * 8,
s->last_frame->data[p] + (y >> 1) * s->last_frame->linesize[p] + (x >> 1),
frame->linesize[p], s->last_frame->linesize[p], 8);
frame->flags &= ~AV_FRAME_FLAG_KEY;
return 0;
} else if (mode == 3) {
memset(dc, bytestream2_get_byte(gbyte), 4);
dc[4] = bytestream2_get_byte(gbyte);
dc[5] = bytestream2_get_byte(gbyte);
@ -228,9 +259,12 @@ static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame,
s->height = bytestream2_get_le16u(&gbyte);
}
ret = ff_set_dimensions(s->avctx, s->width, s->height);
if (ret < 0)
return ret;
if (s->avctx->width != s->width || s->avctx->height != s->height) {
av_frame_unref(s->last_frame);
ret = ff_set_dimensions(s->avctx, s->width, s->height);
if (ret < 0)
return ret;
}
tgq_calculate_qtable(s, bytestream2_get_byteu(&gbyte));
bytestream2_skipu(&gbyte, 3);
@ -238,16 +272,27 @@ static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame,
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;
frame->flags |= AV_FRAME_FLAG_KEY;
for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++)
for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++)
if (tgq_decode_mb(s, &gbyte, frame, y, x) < 0)
return AVERROR_INVALIDDATA;
if ((ret = av_frame_replace(s->last_frame, frame)) < 0)
return ret;
*got_frame = 1;
return avpkt->size;
}
static av_cold int tgq_decode_close(AVCodecContext *avctx)
{
TgqContext *s = avctx->priv_data;
av_frame_free(&s->last_frame);
return 0;
}
const FFCodec ff_eatgq_decoder = {
.p.name = "eatgq",
CODEC_LONG_NAME("Electronic Arts TGQ video"),
@ -255,6 +300,7 @@ const FFCodec ff_eatgq_decoder = {
.p.id = AV_CODEC_ID_TGQ,
.priv_data_size = sizeof(TgqContext),
.init = tgq_decode_init,
.close = tgq_decode_close,
FF_CODEC_DECODE_CB(tgq_decode_frame),
.p.capabilities = AV_CODEC_CAP_DR1,
};

View File

@ -139,7 +139,9 @@ FFFramePool *ff_frame_pool_audio_init(AVBufferRef* (*alloc)(size_t size),
if (ret < 0)
goto fail;
pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL);
if (pool->linesize[0] > SIZE_MAX - align)
goto fail;
pool->pools[0] = av_buffer_pool_init(pool->linesize[0] + align, NULL);
if (!pool->pools[0])
goto fail;
@ -219,7 +221,7 @@ AVFrame *ff_frame_pool_get(FFFramePool *pool)
if (!frame->buf[i])
goto fail;
frame->data[i] = frame->buf[i]->data;
frame->data[i] = (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, pool->align);
}
if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
@ -256,13 +258,15 @@ AVFrame *ff_frame_pool_get(FFFramePool *pool)
frame->buf[i] = av_buffer_pool_get(pool->pools[0]);
if (!frame->buf[i])
goto fail;
frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
frame->extended_data[i] = frame->data[i] =
(uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, pool->align);
}
for (i = 0; i < frame->nb_extended_buf; i++) {
frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]);
if (!frame->extended_buf[i])
goto fail;
frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;
frame->extended_data[i + AV_NUM_DATA_POINTERS] =
(uint8_t *)FFALIGN((uintptr_t)frame->extended_buf[i]->data, pool->align);
}
break;

View File

@ -358,10 +358,12 @@ static int config_props(AVFilterLink *outlink)
} else
outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
av_log(ctx, AV_LOG_TRACE, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d fmt:%s sar:%d/%d\n",
av_log(ctx, AV_LOG_DEBUG, "w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d -> w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d\n",
inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format),
av_color_space_name(inlink->colorspace), av_color_range_name(inlink->color_range),
inlink->sample_aspect_ratio.num, inlink->sample_aspect_ratio.den,
outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format),
av_color_space_name(outlink->colorspace), av_color_range_name(outlink->color_range),
outlink->sample_aspect_ratio.num, outlink->sample_aspect_ratio.den);
return 0;
@ -628,9 +630,12 @@ static int graphs_build(AVFrame *in, AVFrame *out, const AVPixFmtDescriptor *des
if (ret)
return print_zimg_error(ctx);
if (size > (SIZE_MAX - ZIMG_ALIGNMENT))
return AVERROR(ENOMEM);
if (s->tmp[job_nr])
av_freep(&s->tmp[job_nr]);
s->tmp[job_nr] = av_calloc(size, 1);
s->tmp[job_nr] = av_mallocz(size + ZIMG_ALIGNMENT);
if (!s->tmp[job_nr])
return AVERROR(ENOMEM);
@ -657,32 +662,24 @@ static int graphs_build(AVFrame *in, AVFrame *out, const AVPixFmtDescriptor *des
return 0;
}
static int realign_frame(const AVPixFmtDescriptor *desc, AVFrame **frame, int needs_copy)
static int realign_frame(AVFilterLink *link, const AVPixFmtDescriptor *desc, AVFrame **frame)
{
AVFrame *aligned = NULL;
int ret = 0, plane, planes;
/* Realign any unaligned input frame. */
planes = av_pix_fmt_count_planes(desc->nb_components);
planes = av_pix_fmt_count_planes((*frame)->format);
for (plane = 0; plane < planes; plane++) {
int p = desc->comp[plane].plane;
if ((uintptr_t)(*frame)->data[p] % ZIMG_ALIGNMENT || (*frame)->linesize[p] % ZIMG_ALIGNMENT) {
if (!(aligned = av_frame_alloc())) {
ret = AVERROR(ENOMEM);
goto fail;
}
aligned = ff_default_get_video_buffer2(link, (*frame)->width, (*frame)->height, ZIMG_ALIGNMENT);
if (!aligned)
return AVERROR(ENOMEM);
aligned->format = (*frame)->format;
aligned->width = (*frame)->width;
aligned->height = (*frame)->height;
if ((ret = av_frame_get_buffer(aligned, ZIMG_ALIGNMENT)) < 0)
if ((ret = av_frame_copy(aligned, *frame)) < 0)
goto fail;
if (needs_copy && (ret = av_frame_copy(aligned, *frame)) < 0)
goto fail;
if (needs_copy && (ret = av_frame_copy_props(aligned, *frame)) < 0)
if ((ret = av_frame_copy_props(aligned, *frame)) < 0)
goto fail;
av_frame_free(frame);
@ -750,7 +747,9 @@ static int filter_slice(AVFilterContext *ctx, void *data, int job_nr, int n_jobs
}
if (!s->graph[job_nr])
return AVERROR(EINVAL);
ret = zimg_filter_graph_process(s->graph[job_nr], &src_buf, &dst_buf, s->tmp[job_nr], 0, 0, 0, 0);
ret = zimg_filter_graph_process(s->graph[job_nr], &src_buf, &dst_buf,
(uint8_t *)FFALIGN((uintptr_t)s->tmp[job_nr], ZIMG_ALIGNMENT),
0, 0, 0, 0);
if (ret)
return print_zimg_error(ctx);
@ -765,7 +764,9 @@ static int filter_slice(AVFilterContext *ctx, void *data, int job_nr, int n_jobs
if (!s->alpha_graph[job_nr])
return AVERROR(EINVAL);
ret = zimg_filter_graph_process(s->alpha_graph[job_nr], &src_buf, &dst_buf, s->tmp[job_nr], 0, 0, 0, 0);
ret = zimg_filter_graph_process(s->alpha_graph[job_nr], &src_buf, &dst_buf,
(uint8_t *)FFALIGN((uintptr_t)s->tmp[job_nr], ZIMG_ALIGNMENT),
0, 0, 0, 0);
if (ret)
return print_zimg_error(ctx);
}
@ -802,20 +803,17 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
(s->src_format.pixel_type !=s->dst_format.pixel_type) ||
(s->src_format.transfer_characteristics !=s->dst_format.transfer_characteristics)
){
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
out = ff_default_get_video_buffer2(outlink, outlink->w, outlink->h, ZIMG_ALIGNMENT);
if (!out) {
ret = AVERROR(ENOMEM);
goto fail;
}
if ((ret = realign_frame(odesc, &out, 0)) < 0)
goto fail;
av_frame_copy_props(out, in);
out->colorspace = outlink->colorspace;
out->color_range = outlink->color_range;
if ((ret = realign_frame(desc, &in, 1)) < 0)
if ((ret = realign_frame(link, desc, &in)) < 0)
goto fail;
snprintf(buf, sizeof(buf)-1, "%d", outlink->w);

View File

@ -2502,7 +2502,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
pb->eof_reached = 0;
/* Clear any buffered data */
pb->buf_end = pb->buf_ptr = pb->buffer;
/* Reset the pos, to let the mpegts demuxer know we've seeked. */
/* Reset the pos, to let the mpegts/mov demuxer know we've seeked. */
pb->pos = 0;
/* Flush the packet queue of the subdemuxer. */
ff_read_frame_flush(pls->ctx);

View File

@ -10612,15 +10612,15 @@ static int mov_switch_root(AVFormatContext *s, int64_t target, int index)
if (index >= 0 && index < mov->frag_index.nb_items)
target = mov->frag_index.item[index].moof_offset;
if (avio_seek(s->pb, target, SEEK_SET) != target) {
if (target >= 0 && avio_seek(s->pb, target, SEEK_SET) != target) {
av_log(mov->fc, AV_LOG_ERROR, "root atom offset 0x%"PRIx64": partial file\n", target);
return AVERROR_INVALIDDATA;
}
mov->next_root_atom = 0;
if (index < 0 || index >= mov->frag_index.nb_items)
if ((index < 0 && target >= 0) || index >= mov->frag_index.nb_items)
index = search_frag_moof_offset(&mov->frag_index, target);
if (index < mov->frag_index.nb_items &&
if (index >= 0 && index < mov->frag_index.nb_items &&
mov->frag_index.item[index].moof_offset == target) {
if (index + 1 < mov->frag_index.nb_items)
mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
@ -10750,10 +10750,43 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
MOVStreamContext *sc;
AVIndexEntry *sample;
AVStream *st = NULL;
FFStream *avsti = NULL;
int64_t current_index;
int ret;
int i;
mov->fc = s;
retry:
if (s->pb->pos == 0) {
// Discard current fragment index
if (mov->frag_index.allocated_size > 0) {
av_freep(&mov->frag_index.item);
mov->frag_index.nb_items = 0;
mov->frag_index.allocated_size = 0;
mov->frag_index.current = -1;
mov->frag_index.complete = 0;
}
for (i = 0; i < s->nb_streams; i++) {
AVStream *avst = s->streams[i];
MOVStreamContext *msc = avst->priv_data;
// Clear current sample
mov_current_sample_set(msc, 0);
msc->ctts_index = 0;
// Discard current index entries
avsti = ffstream(avst);
if (avsti->index_entries_allocated_size > 0) {
av_freep(&avsti->index_entries);
avsti->index_entries_allocated_size = 0;
avsti->nb_index_entries = 0;
}
}
if ((ret = mov_switch_root(s, -1, -1)) < 0)
return ret;
}
sample = mov_find_next_sample(s, &st);
if (!sample || (mov->next_root_atom && sample->pos > mov->next_root_atom)) {
if (!mov->next_root_atom)