[FFmpeg-devel] [PATCH] avformat/riffenc: indicate storage of flipped RGB bitmaps
Gyan Doshi
ffmpeg at gyani.pro
Tue Jul 14 11:38:48 EEST 2020
On 14-07-2020 01:54 pm, Paul B Mahol wrote:
> Why is option called rgb?
> It have nothing to do with rgb.
>
> Flipped can be any encoded file.
No, coded or uncoded streams with a codec tag or raw YUV bitmaps are
always indicated as positive height. Only raw RGB bitmaps can be
signaled as flipped.
See doc for |biHeight in
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader#members
or the end of this page
https://docs.microsoft.com/en-us/windows/win32/directshow/top-down-vs--bottom-up-dibs
Regards,
Gyan
|
>
> On 7/14/20, Gyan Doshi <ffmpeg at gyani.pro> wrote:
>> Plan to push in 24h.
>>
>> On 08-07-2020 06:21 pm, Gyan Doshi wrote:
>>> Some legacy applications such as AVI2MVE expect raw RGB bitmaps
>>> to be stored bottom-up, whereas our RIFF BITMAPINFOHEADER assumes
>>> they are always stored top-down and thus write a negative value
>>> for height. This can prevent reading of these files.
>>>
>>> Option flipped_raw_rgb added to AVI and Matroska muxers
>>> which will write positive value for height when enabled.
>>>
>>> Note that the user has to flip the bitmaps beforehand using other
>>> means such as the vflip filter.
>>> ---
>>> doc/muxers.texi | 13 +++++++++++++
>>> libavformat/asfenc.c | 2 +-
>>> libavformat/avienc.c | 4 +++-
>>> libavformat/matroskaenc.c | 5 ++++-
>>> libavformat/riff.h | 2 +-
>>> libavformat/riffenc.c | 7 ++++---
>>> libavformat/wtvenc.c | 2 +-
>>> 7 files changed, 27 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/doc/muxers.texi b/doc/muxers.texi
>>> index b1389a3227..2f26494bfa 100644
>>> --- a/doc/muxers.texi
>>> +++ b/doc/muxers.texi
>>> @@ -89,6 +89,12 @@ specific scenarios, e.g. when merging multiple audio
>>> streams into one for
>>> compatibility with software that only supports a single audio stream in
>>> AVI
>>> (see @ref{amerge,,the "amerge" section in the ffmpeg-filters
>>> manual,ffmpeg-filters}).
>>>
>>> + at item flipped_raw_rgb
>>> +If set to true, store positive height for raw RGB bitmaps, which
>>> indicates
>>> +bitmap is stored bottom-up. Note that this option does not flip the
>>> bitmap
>>> +which has to be done manually beforehand, e.g. by using the vflip filter.
>>> +Default is @var{false} and indicates bitmap is stored top down.
>>> +
>>> @end table
>>>
>>> @anchor{chromaprint}
>>> @@ -1409,6 +1415,13 @@ disposition default exists, no subtitle track will
>>> be marked as default.
>>> In this mode the FlagDefault is set if and only if the
>>> AV_DISPOSITION_DEFAULT
>>> flag is set in the disposition of the corresponding stream.
>>> @end table
>>> +
>>> + at item flipped_raw_rgb
>>> +If set to true, store positive height for raw RGB bitmaps, which
>>> indicates
>>> +bitmap is stored bottom-up. Note that this option does not flip the
>>> bitmap
>>> +which has to be done manually beforehand, e.g. by using the vflip filter.
>>> +Default is @var{false} and indicates bitmap is stored top down.
>>> +
>>> @end table
>>>
>>> @anchor{md5}
>>> diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c
>>> index 73afb13200..8b24264c94 100644
>>> --- a/libavformat/asfenc.c
>>> +++ b/libavformat/asfenc.c
>>> @@ -682,7 +682,7 @@ static int asf_write_header1(AVFormatContext *s,
>>> int64_t file_size,
>>> avio_wl16(pb, 40 + par->extradata_size); /* size */
>>>
>>> /* BITMAPINFOHEADER header */
>>> - ff_put_bmp_header(pb, par, 1, 0);
>>> + ff_put_bmp_header(pb, par, 1, 0, 0);
>>> }
>>> end_header(pb, hpos);
>>> }
>>> diff --git a/libavformat/avienc.c b/libavformat/avienc.c
>>> index 297d5b8964..1b2cb529b9 100644
>>> --- a/libavformat/avienc.c
>>> +++ b/libavformat/avienc.c
>>> @@ -72,6 +72,7 @@ typedef struct AVIContext {
>>> int reserve_index_space;
>>> int master_index_max_size;
>>> int write_channel_mask;
>>> + int flipped_raw_rgb;
>>> } AVIContext;
>>>
>>> typedef struct AVIStream {
>>> @@ -449,7 +450,7 @@ static int avi_write_header(AVFormatContext *s)
>>> && par->bits_per_coded_sample == 15)
>>> par->bits_per_coded_sample = 16;
>>> avist->pal_offset = avio_tell(pb) + 40;
>>> - ff_put_bmp_header(pb, par, 0, 0);
>>> + ff_put_bmp_header(pb, par, 0, 0, avi->flipped_raw_rgb);
>>> pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi,
>>>
>>> par->bits_per_coded_sample);
>>> if ( !par->codec_tag
>>> @@ -993,6 +994,7 @@ static void avi_deinit(AVFormatContext *s)
>>> static const AVOption options[] = {
>>> { "reserve_index_space", "reserve space (in bytes) at the beginning
>>> of the file for each stream index", OFFSET(reserve_index_space),
>>> AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, ENC },
>>> { "write_channel_mask", "write channel mask into wave format
>>> header", OFFSET(write_channel_mask), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
>>> ENC },
>>> + { "flipped_raw_rgb", "Raw RGB bitmaps are stored bottom-up",
>>> OFFSET(flipped_raw_rgb), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC },
>>> { NULL },
>>> };
>>>
>>> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
>>> index 105ed5197e..233c472b8f 100644
>>> --- a/libavformat/matroskaenc.c
>>> +++ b/libavformat/matroskaenc.c
>>> @@ -154,6 +154,7 @@ typedef struct MatroskaMuxContext {
>>> int is_dash;
>>> int dash_track_number;
>>> int allow_raw_vfw;
>>> + int flipped_raw_rgb;
>>> int default_mode;
>>>
>>> uint32_t segment_uid[4];
>>> @@ -764,6 +765,7 @@ static int mkv_write_codecprivate(AVFormatContext *s,
>>> AVIOContext *pb,
>>> int native_id, int qt_id)
>>> {
>>> AVIOContext *dyn_cp;
>>> + MatroskaMuxContext *mkv = s->priv_data;
>>> uint8_t *codecpriv;
>>> int ret, codecpriv_size;
>>>
>>> @@ -802,7 +804,7 @@ static int mkv_write_codecprivate(AVFormatContext *s,
>>> AVIOContext *pb,
>>> ret = AVERROR(EINVAL);
>>> }
>>>
>>> - ff_put_bmp_header(dyn_cp, par, 0, 0);
>>> + ff_put_bmp_header(dyn_cp, par, 0, 0, mkv->flipped_raw_rgb);
>>> }
>>> } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
>>> unsigned int tag;
>>> @@ -2787,6 +2789,7 @@ static const AVOption options[] = {
>>> { "dash_track_number", "Track number for the DASH stream",
>>> OFFSET(dash_track_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX,
>>> FLAGS },
>>> { "live", "Write files assuming it is a live stream.",
>>> OFFSET(is_live), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
>>> { "allow_raw_vfw", "allow RAW VFW mode", OFFSET(allow_raw_vfw),
>>> AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
>>> + { "flipped_raw_rgb", "Raw RGB bitmaps in VFW mode are stored
>>> bottom-up", OFFSET(flipped_raw_rgb), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1,
>>> FLAGS },
>>> { "write_crc32", "write a CRC32 element inside every Level 1
>>> element", OFFSET(write_crc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS
>>> },
>>> { "default_mode", "Controls how a track's FlagDefault is inferred",
>>> OFFSET(default_mode), AV_OPT_TYPE_INT, { .i64 = DEFAULT_MODE_INFER },
>>> DEFAULT_MODE_INFER, DEFAULT_MODE_PASSTHROUGH, FLAGS, "default_mode" },
>>> { "infer", "For each track type, mark the first track of disposition
>>> default as default; if none exists, mark the first track as default.", 0,
>>> AV_OPT_TYPE_CONST, { .i64 = DEFAULT_MODE_INFER }, 0, 0, FLAGS,
>>> "default_mode" },
>>> diff --git a/libavformat/riff.h b/libavformat/riff.h
>>> index 21078b77c8..127138d2bc 100644
>>> --- a/libavformat/riff.h
>>> +++ b/libavformat/riff.h
>>> @@ -46,7 +46,7 @@ void ff_end_tag(AVIOContext *pb, int64_t start);
>>> */
>>> int ff_get_bmp_header(AVIOContext *pb, AVStream *st, uint32_t *size);
>>>
>>> -void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, int
>>> for_asf, int ignore_extradata);
>>> +void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, int
>>> for_asf, int ignore_extradata, int rgb_frame_is_flipped);
>>>
>>> /**
>>> * Tell ff_put_wav_header() to use WAVEFORMATEX even for PCM codecs.
>>> diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c
>>> index c04d55c423..d0ee98bfcc 100644
>>> --- a/libavformat/riffenc.c
>>> +++ b/libavformat/riffenc.c
>>> @@ -207,10 +207,11 @@ int ff_put_wav_header(AVFormatContext *s,
>>> AVIOContext *pb,
>>>
>>> /* BITMAPINFOHEADER header */
>>> void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par,
>>> - int for_asf, int ignore_extradata)
>>> + int for_asf, int ignore_extradata, int
>>> rgb_frame_is_flipped)
>>> {
>>> - int keep_height = par->extradata_size >= 9 &&
>>> - !memcmp(par->extradata + par->extradata_size - 9,
>>> "BottomUp", 9);
>>> + int keep_height = (par->extradata_size >= 9 &&
>>> + !memcmp(par->extradata + par->extradata_size - 9,
>>> "BottomUp", 9)) ||
>>> + rgb_frame_is_flipped;
>>> int extradata_size = par->extradata_size - 9*keep_height;
>>> enum AVPixelFormat pix_fmt = par->format;
>>> int pal_avi;
>>> diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c
>>> index 498bc64019..b53fdf9048 100644
>>> --- a/libavformat/wtvenc.c
>>> +++ b/libavformat/wtvenc.c
>>> @@ -241,7 +241,7 @@ static void put_videoinfoheader2(AVIOContext *pb,
>>> AVStream *st)
>>> avio_wl32(pb, 0);
>>> avio_wl32(pb, 0);
>>>
>>> - ff_put_bmp_header(pb, st->codecpar, 0, 1);
>>> + ff_put_bmp_header(pb, st->codecpar, 0, 1, 0);
>>>
>>> if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
>>> int padding = (st->codecpar->extradata_size & 3) ? 4 -
>>> (st->codecpar->extradata_size & 3) : 0;
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel at ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
More information about the ffmpeg-devel
mailing list