- Fix on AVI and WAV headers based on Nikolai Zhubr patch.

- Now the properties of the AVIs are correctly shown, but the MP2 audio
isn't playable, it seems the problems is that Fraunhoffer MP3 decoder
included on Windows cannot decode MP2 streams.

Originally committed as revision 316 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Juanjo 23 years ago
parent f5d1f41b11
commit 86bec9a161
  1. 74
      libav/avienc.c
  2. 29
      libav/wav.c

@ -31,7 +31,8 @@ typedef struct AVIIndex {
} AVIIndex; } AVIIndex;
typedef struct { typedef struct {
offset_t movi_list; offset_t movi_list, frames_hdr_all, frames_hdr_strm[MAX_STREAMS];
int audio_strm_length[MAX_STREAMS];
AVIIndex *first, *last; AVIIndex *first, *last;
} AVIContext; } AVIContext;
@ -109,11 +110,36 @@ void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc)
put_le32(pb, 0); put_le32(pb, 0);
} }
void parse_specific_params(AVCodecContext *stream, int *au_byterate, int *au_ssize, int *au_scale)
{
switch(stream->codec_id) {
case CODEC_ID_PCM_S16LE:
*au_scale = *au_ssize = 2*stream->channels;
*au_byterate = *au_ssize * stream->sample_rate;
break;
case CODEC_ID_PCM_U8:
case CODEC_ID_PCM_ALAW:
case CODEC_ID_PCM_MULAW:
*au_scale = *au_ssize = stream->channels;
*au_byterate = *au_ssize * stream->sample_rate;
break;
case CODEC_ID_MP2:
*au_ssize = 1;
*au_scale = 1;
*au_byterate = stream->bit_rate / 8;
default:
*au_ssize = 1;
*au_scale = 1;
*au_byterate = stream->bit_rate / 8;
break;
}
}
static int avi_write_header(AVFormatContext *s) static int avi_write_header(AVFormatContext *s)
{ {
AVIContext *avi; AVIContext *avi;
ByteIOContext *pb = &s->pb; ByteIOContext *pb = &s->pb;
int bitrate, n, i, nb_frames; int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
AVCodecContext *stream, *video_enc; AVCodecContext *stream, *video_enc;
offset_t list1, list2, strh, strf; offset_t list1, list2, strh, strf;
@ -154,6 +180,7 @@ static int avi_write_header(AVFormatContext *s)
put_le32(pb, bitrate / 8); /* XXX: not quite exact */ put_le32(pb, bitrate / 8); /* XXX: not quite exact */
put_le32(pb, 0); /* padding */ put_le32(pb, 0); /* padding */
put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */
put_le32(pb, nb_frames); /* nb frames, filled later */ put_le32(pb, nb_frames); /* nb frames, filled later */
put_le32(pb, 0); /* initial frame */ put_le32(pb, 0); /* initial frame */
put_le32(pb, s->nb_streams); /* nb streams */ put_le32(pb, s->nb_streams); /* nb streams */
@ -185,9 +212,10 @@ static int avi_write_header(AVFormatContext *s)
put_le32(pb, 1000); /* scale */ put_le32(pb, 1000); /* scale */
put_le32(pb, (1000 * stream->frame_rate) / FRAME_RATE_BASE); /* rate */ put_le32(pb, (1000 * stream->frame_rate) / FRAME_RATE_BASE); /* rate */
put_le32(pb, 0); /* start */ put_le32(pb, 0); /* start */
avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
put_le32(pb, nb_frames); /* length, XXX: fill later */ put_le32(pb, nb_frames); /* length, XXX: fill later */
put_le32(pb, 1024 * 1024); /* suggested buffer size */ put_le32(pb, 1024 * 1024); /* suggested buffer size */
put_le32(pb, 10000); /* quality */ put_le32(pb, -1); /* quality */
put_le32(pb, stream->width * stream->height * 3); /* sample size */ put_le32(pb, stream->width * stream->height * 3); /* sample size */
put_le16(pb, 0); put_le16(pb, 0);
put_le16(pb, 0); put_le16(pb, 0);
@ -196,18 +224,20 @@ static int avi_write_header(AVFormatContext *s)
break; break;
case CODEC_TYPE_AUDIO: case CODEC_TYPE_AUDIO:
put_tag(pb, "auds"); put_tag(pb, "auds");
put_le32(pb, 0); put_le32(pb, 1); /* tag */
put_le32(pb, 0); /* flags */ put_le32(pb, 0); /* flags */
put_le16(pb, 0); /* priority */ put_le16(pb, 0); /* priority */
put_le16(pb, 0); /* language */ put_le16(pb, 0); /* language */
put_le32(pb, 0); /* initial frame */ put_le32(pb, 0); /* initial frame */
put_le32(pb, 1); /* scale */ parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
put_le32(pb, stream->bit_rate / 8); /* rate */ put_le32(pb, au_scale); /* scale */
put_le32(pb, au_byterate); /* rate */
put_le32(pb, 0); /* start */ put_le32(pb, 0); /* start */
avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
put_le32(pb, 0); /* length, XXX: filled later */ put_le32(pb, 0); /* length, XXX: filled later */
put_le32(pb, 12 * 1024); /* suggested buffer size */ put_le32(pb, 12 * 1024); /* suggested buffer size */
put_le32(pb, -1); /* quality */ put_le32(pb, -1); /* quality */
put_le32(pb, 1); /* sample size */ put_le32(pb, au_ssize); /* sample size */
put_le32(pb, 0); put_le32(pb, 0);
put_le32(pb, 0); put_le32(pb, 0);
break; break;
@ -265,6 +295,8 @@ static int avi_write_packet(AVFormatContext *s, int stream_index,
tag[3] = 'b'; tag[3] = 'b';
flags = 0x10; flags = 0x10;
} }
if (enc->codec_type == CODEC_TYPE_AUDIO)
avi->audio_strm_length[stream_index] += size;
if (!url_is_streamed(&s->pb)) { if (!url_is_streamed(&s->pb)) {
idx = malloc(sizeof(AVIIndex)); idx = malloc(sizeof(AVIIndex));
@ -295,6 +327,8 @@ static int avi_write_trailer(AVFormatContext *s)
ByteIOContext *pb = &s->pb; ByteIOContext *pb = &s->pb;
AVIContext *avi = s->priv_data; AVIContext *avi = s->priv_data;
offset_t file_size, idx_chunk; offset_t file_size, idx_chunk;
int n, nb_frames, au_byterate, au_ssize, au_scale;
AVCodecContext *stream;
AVIIndex *idx; AVIIndex *idx;
if (!url_is_streamed(&s->pb)) { if (!url_is_streamed(&s->pb)) {
@ -315,6 +349,32 @@ static int avi_write_trailer(AVFormatContext *s)
file_size = url_ftell(pb); file_size = url_ftell(pb);
url_fseek(pb, 4, SEEK_SET); url_fseek(pb, 4, SEEK_SET);
put_le32(pb, (UINT32)(file_size - 8)); put_le32(pb, (UINT32)(file_size - 8));
/* Fill in frame/sample counters */
nb_frames = 0;
for(n=0;n<s->nb_streams;n++) {
if (avi->frames_hdr_strm[n] != 0) {
stream = &s->streams[n]->codec;
url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET);
if (stream->codec_type == CODEC_TYPE_VIDEO) {
put_le32(pb, stream->frame_number);
if (nb_frames < stream->frame_number)
nb_frames = stream->frame_number;
} else {
if (stream->codec_id == CODEC_ID_MP2) {
put_le32(pb, stream->frame_number);
nb_frames += stream->frame_number;
} else {
parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
put_le32(pb, avi->audio_strm_length[n] / au_ssize);
}
}
}
}
if (avi->frames_hdr_all != 0) {
url_fseek(pb, avi->frames_hdr_all, SEEK_SET);
put_le32(pb, nb_frames);
}
url_fseek(pb, file_size, SEEK_SET); url_fseek(pb, file_size, SEEK_SET);
} }
put_flush_packet(pb); put_flush_packet(pb);

@ -33,7 +33,7 @@ CodecTag codec_wav_tags[] = {
/* WAVEFORMATEX header */ /* WAVEFORMATEX header */
int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
{ {
int tag, bps; int tag, bps, blkalign, bytespersec;
tag = codec_get_tag(codec_wav_tags, enc->codec_id); tag = codec_get_tag(codec_wav_tags, enc->codec_id);
if (tag == 0) if (tag == 0)
@ -41,18 +41,39 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
put_le16(pb, tag); put_le16(pb, tag);
put_le16(pb, enc->channels); put_le16(pb, enc->channels);
put_le32(pb, enc->sample_rate); put_le32(pb, enc->sample_rate);
put_le32(pb, enc->bit_rate / 8);
put_le16(pb, 1); /* block align */
if (enc->codec_id == CODEC_ID_PCM_U8 || if (enc->codec_id == CODEC_ID_PCM_U8 ||
enc->codec_id == CODEC_ID_PCM_ALAW || enc->codec_id == CODEC_ID_PCM_ALAW ||
enc->codec_id == CODEC_ID_PCM_MULAW) { enc->codec_id == CODEC_ID_PCM_MULAW) {
bps = 8; bps = 8;
} else if (enc->codec_id == CODEC_ID_MP2) {
bps = 0;
} else { } else {
bps = 16; bps = 16;
} }
put_le16(pb, bps); /* bits per sample */
if (enc->codec_id == CODEC_ID_MP2)
blkalign = 1;
else
blkalign = enc->channels*bps >> 3;
if (enc->codec_id == CODEC_ID_PCM_U8 ||
enc->codec_id == CODEC_ID_PCM_S16LE) {
bytespersec = enc->sample_rate * blkalign;
} else {
bytespersec = enc->bit_rate / 8;
}
put_le32(pb, bytespersec); /* bytes per second */
put_le16(pb, blkalign); /* block align */
put_le16(pb, bps); /* bits per sample */
if (enc->codec_id == CODEC_ID_MP2) {
put_le16(pb, 12); /* wav_extra_size */
put_le16(pb, 1); /* wID */
put_le32(pb, 2); /* fdwFlags */
put_le16(pb, 1152); /* nBlockSize */
put_le16(pb, 1); /* nFramesPerBlock */
put_le16(pb, 1393); /* nCodecDelay */
} else
put_le16(pb, 0); /* wav_extra_size */ put_le16(pb, 0); /* wav_extra_size */
return 0; return 0;
} }

Loading…
Cancel
Save