[FFmpeg-devel] [PATCH 2/3] ff_put_wav_header: add flag to omit 0 cbSize field

Daniel Verkamp daniel at drv.nu
Tue Mar 18 08:40:51 CET 2014


For a specific example, see "[FFmpeg-devel] Wave header" thread from
last year [1].

-flags +bitexact is still needed to produce "normal" WAV files; it may
be worth considering whether the INFO tag should be written by
default.  Clearly tools that don't properly interpret the headers are
broken, but it is probably better to produce files that work rather
than files with the mostly-useless-for-WAV encoder information by
default.

Thanks,
-- Daniel

[1]: http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2013-April/142560.html


On Tue, Mar 18, 2014 at 12:29 AM, Daniel Verkamp <daniel at drv.nu> wrote:
> Partially undoes commit 2c4e08d89327595f7f4be57dda4b3775e1198d5e:
>
>     riff: always generate a proper WAVEFORMATEX structure in
>     ff_put_wav_header
>
> The WAV format muxer will now only write out cbSize if necessary (e.g.
> if it is not zero).  This produces WAV files that are out of spec
> according to current Microsoft WAVEFORMATEX documentation, but it is
> more consistent with other tools that produce WAV files.  The WAV
> files produced in this way are more compatible with a wider range of
> tools.
> ---
>  libavformat/asfenc.c      |  2 +-
>  libavformat/avienc.c      |  2 +-
>  libavformat/matroskaenc.c |  2 +-
>  libavformat/movenc.c      |  4 ++--
>  libavformat/riff.h        | 17 ++++++++++++++++-
>  libavformat/riffenc.c     |  5 +++--
>  libavformat/wavenc.c      |  8 ++++++--
>  libavformat/wtvenc.c      |  2 +-
>  8 files changed, 31 insertions(+), 11 deletions(-)
>
> diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c
> index b456730..4fdc852 100644
> --- a/libavformat/asfenc.c
> +++ b/libavformat/asfenc.c
> @@ -491,7 +491,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
>
>          if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
>              /* WAVEFORMATEX header */
> -            int wavsize = ff_put_wav_header(pb, enc);
> +            int wavsize = ff_put_wav_header(pb, enc, 0);
>
>              if (wavsize < 0)
>                  return -1;
> diff --git a/libavformat/avienc.c b/libavformat/avienc.c
> index 24a3821..dd31308 100644
> --- a/libavformat/avienc.c
> +++ b/libavformat/avienc.c
> @@ -308,7 +308,7 @@ static int avi_write_header(AVFormatContext *s)
>                  ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0, 0);
>                  break;
>              case AVMEDIA_TYPE_AUDIO:
> -                if ((ret = ff_put_wav_header(pb, stream)) < 0)
> +                if ((ret = ff_put_wav_header(pb, stream, 0)) < 0)
>                      return ret;
>                  break;
>              default:
> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> index 7d83665..0bdc33b 100644
> --- a/libavformat/matroskaenc.c
> +++ b/libavformat/matroskaenc.c
> @@ -590,7 +590,7 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo
>          if (!codec->codec_tag)
>              codec->codec_tag = tag;
>
> -        ff_put_wav_header(dyn_cp, codec);
> +        ff_put_wav_header(dyn_cp, codec, 0);
>      }
>
>      codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv);
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 899fdb6..9ca9f3a 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -395,7 +395,7 @@ static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
>      avio_wb32(pb, 0);
>      avio_wl32(pb, track->tag); // store it byteswapped
>      track->enc->codec_tag = av_bswap16(track->tag >> 16);
> -    ff_put_wav_header(pb, track->enc);
> +    ff_put_wav_header(pb, track->enc, 0);
>      return update_size(pb, pos);
>  }
>
> @@ -404,7 +404,7 @@ static int mov_write_wfex_tag(AVIOContext *pb, MOVTrack *track)
>      int64_t pos = avio_tell(pb);
>      avio_wb32(pb, 0);
>      ffio_wfourcc(pb, "wfex");
> -    ff_put_wav_header(pb, track->enc);
> +    ff_put_wav_header(pb, track->enc, 0);
>      return update_size(pb, pos);
>  }
>
> diff --git a/libavformat/riff.h b/libavformat/riff.h
> index dba3803..480cfdc 100644
> --- a/libavformat/riff.h
> +++ b/libavformat/riff.h
> @@ -46,7 +46,22 @@ void ff_end_tag(AVIOContext *pb, int64_t start);
>  int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize);
>
>  void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *tags, int for_asf, int ignore_extradata);
> -int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc);
> +
> +/**
> + * Tell ff_put_wav_header() not to write out the cbSize field of WAVEFORMATEX
> + * header if it is 0.
> + */
> +#define FF_PUT_WAV_HEADER_OMIT_ZERO_CBSIZE  0x00000001
> +
> +/**
> + * Write WAVEFORMAT header structure.
> + *
> + * @param flags a combination of FF_PUT_WAV_HEADER_* constants
> + *
> + * @return the size or -1 on error
> + */
> +int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags);
> +
>  enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps);
>  int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size);
>
> diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c
> index c3e3e66..7114a16 100644
> --- a/libavformat/riffenc.c
> +++ b/libavformat/riffenc.c
> @@ -51,7 +51,7 @@ void ff_end_tag(AVIOContext *pb, int64_t start)
>
>  /* WAVEFORMATEX header */
>  /* returns the size or -1 on error */
> -int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
> +int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags)
>  {
>      int bps, blkalign, bytespersec, frame_size;
>      int hdrsize;
> @@ -187,7 +187,8 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc)
>          avio_wl32(pb, 0xAA000080);
>          avio_wl32(pb, 0x719B3800);
>          }
> -    } else {
> +    } else if (riff_extradata - riff_extradata_start ||
> +               !(flags & FF_PUT_WAV_HEADER_OMIT_ZERO_CBSIZE)) {
>          avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
>      }
>      avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start);
> diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c
> index 0067dfe..1b08cae 100644
> --- a/libavformat/wavenc.c
> +++ b/libavformat/wavenc.c
> @@ -115,6 +115,7 @@ static int wav_write_header(AVFormatContext *s)
>      WAVMuxContext *wav = s->priv_data;
>      AVIOContext *pb = s->pb;
>      int64_t fmt;
> +    int hdrflags = 0;
>
>      if (s->nb_streams != 1) {
>          av_log(s, AV_LOG_ERROR, "WAVE files have exactly one stream\n");
> @@ -141,7 +142,10 @@ static int wav_write_header(AVFormatContext *s)
>
>      /* format header */
>      fmt = ff_start_tag(pb, "fmt ");
> -    if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) {
> +    if (s->streams[0]->codec->strict_std_compliance <= FF_COMPLIANCE_NORMAL) {
> +        hdrflags |= FF_PUT_WAV_HEADER_OMIT_ZERO_CBSIZE;
> +    }
> +    if (ff_put_wav_header(pb, s->streams[0]->codec, hdrflags) < 0) {
>          av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
>                 s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
>          return -1;
> @@ -323,7 +327,7 @@ static int w64_write_header(AVFormatContext *s)
>      avio_wl64(pb, -1);
>      avio_write(pb, ff_w64_guid_wave, sizeof(ff_w64_guid_wave));
>      start_guid(pb, ff_w64_guid_fmt, &start);
> -    if ((ret = ff_put_wav_header(pb, s->streams[0]->codec)) < 0) {
> +    if ((ret = ff_put_wav_header(pb, s->streams[0]->codec, 0)) < 0) {
>          av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
>                 s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
>          return ret;
> diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c
> index b82ff0b..7f50230 100644
> --- a/libavformat/wtvenc.c
> +++ b/libavformat/wtvenc.c
> @@ -287,7 +287,7 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
>      if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
>          put_videoinfoheader2(pb, st);
>      } else {
> -        if (ff_put_wav_header(pb, st->codec) < 0)
> +        if (ff_put_wav_header(pb, st->codec, 0) < 0)
>              format_type = &ff_format_none;
>      }
>      hdr_size = avio_tell(pb) - hdr_pos_start;
> --
> 1.9.0
>


More information about the ffmpeg-devel mailing list