mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
correct pcm audio format handling
Originally committed as revision 147 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
96baaa6aff
commit
46a3d0685d
14
libav/asf.c
14
libav/asf.c
@ -301,7 +301,8 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
|
|||||||
|
|
||||||
if (enc->codec_type == CODEC_TYPE_AUDIO) {
|
if (enc->codec_type == CODEC_TYPE_AUDIO) {
|
||||||
/* WAVEFORMATEX header */
|
/* WAVEFORMATEX header */
|
||||||
put_wav_header(pb, enc);
|
if (put_wav_header(pb, enc) < 0)
|
||||||
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
put_le32(pb, enc->width);
|
put_le32(pb, enc->width);
|
||||||
put_le32(pb, enc->height);
|
put_le32(pb, enc->height);
|
||||||
@ -376,7 +377,10 @@ static int asf_write_header(AVFormatContext *s)
|
|||||||
asf->packet_size = PACKET_SIZE;
|
asf->packet_size = PACKET_SIZE;
|
||||||
asf->nb_packets = 0;
|
asf->nb_packets = 0;
|
||||||
|
|
||||||
asf_write_header1(s, 0, 24);
|
if (asf_write_header1(s, 0, 24) < 0) {
|
||||||
|
free(asf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
put_flush_packet(&s->pb);
|
put_flush_packet(&s->pb);
|
||||||
|
|
||||||
@ -637,7 +641,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
ByteIOContext *pb = &s->pb;
|
ByteIOContext *pb = &s->pb;
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
ASFStream *asf_st;
|
ASFStream *asf_st;
|
||||||
int size, i;
|
int size, i, bps;
|
||||||
INT64 gsize;
|
INT64 gsize;
|
||||||
|
|
||||||
asf = av_mallocz(sizeof(ASFContext));
|
asf = av_mallocz(sizeof(ASFContext));
|
||||||
@ -710,12 +714,12 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
if (type == CODEC_TYPE_AUDIO) {
|
if (type == CODEC_TYPE_AUDIO) {
|
||||||
id = get_le16(pb);
|
id = get_le16(pb);
|
||||||
st->codec.codec_tag = id;
|
st->codec.codec_tag = id;
|
||||||
st->codec.codec_id = codec_get_id(codec_wav_tags, id);
|
|
||||||
st->codec.channels = get_le16(pb);
|
st->codec.channels = get_le16(pb);
|
||||||
st->codec.sample_rate = get_le32(pb);
|
st->codec.sample_rate = get_le32(pb);
|
||||||
st->codec.bit_rate = get_le32(pb) * 8;
|
st->codec.bit_rate = get_le32(pb) * 8;
|
||||||
get_le16(pb); /* block align */
|
get_le16(pb); /* block align */
|
||||||
get_le16(pb); /* bits per sample */
|
bps = get_le16(pb); /* bits per sample */
|
||||||
|
st->codec.codec_id = wav_codec_get_id(id, bps);
|
||||||
size = get_le16(pb);
|
size = get_le16(pb);
|
||||||
url_fskip(pb, size);
|
url_fskip(pb, size);
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,7 +10,8 @@ offset_t start_tag(ByteIOContext *pb, char *tag);
|
|||||||
void end_tag(ByteIOContext *pb, offset_t start);
|
void end_tag(ByteIOContext *pb, offset_t start);
|
||||||
|
|
||||||
void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc);
|
void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc);
|
||||||
void put_wav_header(ByteIOContext *pb, AVCodecContext *enc);
|
int put_wav_header(ByteIOContext *pb, AVCodecContext *enc);
|
||||||
|
int wav_codec_get_id(unsigned int tag, int bps);
|
||||||
|
|
||||||
typedef struct CodecTag {
|
typedef struct CodecTag {
|
||||||
int id;
|
int id;
|
||||||
|
@ -51,7 +51,7 @@ int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
ByteIOContext *pb = &s->pb;
|
ByteIOContext *pb = &s->pb;
|
||||||
UINT32 tag, tag1;
|
UINT32 tag, tag1;
|
||||||
int codec_type, stream_index, size, frame_period, bit_rate;
|
int codec_type, stream_index, size, frame_period, bit_rate;
|
||||||
int i;
|
int i, bps;
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
|
|
||||||
avi = malloc(sizeof(AVIContext));
|
avi = malloc(sizeof(AVIContext));
|
||||||
@ -169,14 +169,16 @@ int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
|||||||
tag1 = get_le16(pb);
|
tag1 = get_le16(pb);
|
||||||
st->codec.codec_type = CODEC_TYPE_AUDIO;
|
st->codec.codec_type = CODEC_TYPE_AUDIO;
|
||||||
st->codec.codec_tag = tag1;
|
st->codec.codec_tag = tag1;
|
||||||
st->codec.codec_id = codec_get_id(codec_wav_tags, tag1);
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("audio: 0x%x\n", tag1);
|
printf("audio: 0x%x\n", tag1);
|
||||||
#endif
|
#endif
|
||||||
st->codec.channels = get_le16(pb);
|
st->codec.channels = get_le16(pb);
|
||||||
st->codec.sample_rate = get_le32(pb);
|
st->codec.sample_rate = get_le32(pb);
|
||||||
st->codec.bit_rate = get_le32(pb) * 8;
|
st->codec.bit_rate = get_le32(pb) * 8;
|
||||||
url_fskip(pb, size - 3 * 4);
|
get_le16(pb); /* block align */
|
||||||
|
bps = get_le16(pb);
|
||||||
|
st->codec.codec_id = wav_codec_get_id(tag1, bps);
|
||||||
|
url_fskip(pb, size - 4 * 4);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
url_fskip(pb, size);
|
url_fskip(pb, size);
|
||||||
|
@ -67,17 +67,6 @@ CodecTag codec_bmp_tags[] = {
|
|||||||
{ 0, 0 },
|
{ 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
CodecTag codec_wav_tags[] = {
|
|
||||||
{ CODEC_ID_MP2, 0x55 },
|
|
||||||
{ CODEC_ID_MP2, 0x50 },
|
|
||||||
{ CODEC_ID_AC3, 0x2000 },
|
|
||||||
{ CODEC_ID_PCM_S16LE, 0x01 },
|
|
||||||
{ CODEC_ID_PCM_ALAW, 0x06 },
|
|
||||||
{ CODEC_ID_PCM_MULAW, 0x07 },
|
|
||||||
{ 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int codec_get_tag(CodecTag *tags, int id)
|
unsigned int codec_get_tag(CodecTag *tags, int id)
|
||||||
{
|
{
|
||||||
while (tags->id != 0) {
|
while (tags->id != 0) {
|
||||||
@ -120,22 +109,6 @@ void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc)
|
|||||||
put_le32(pb, 0);
|
put_le32(pb, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WAVEFORMATEX header */
|
|
||||||
void put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
|
|
||||||
{
|
|
||||||
int tag;
|
|
||||||
|
|
||||||
tag = codec_get_tag(codec_wav_tags, enc->codec_id);
|
|
||||||
|
|
||||||
put_le16(pb, tag);
|
|
||||||
put_le16(pb, enc->channels);
|
|
||||||
put_le32(pb, enc->sample_rate);
|
|
||||||
put_le32(pb, enc->bit_rate / 8);
|
|
||||||
put_le16(pb, 1); /* block align */
|
|
||||||
put_le16(pb, 16); /* bits per sample */
|
|
||||||
put_le16(pb, 0); /* wav_extra_size */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int avi_write_header(AVFormatContext *s)
|
static int avi_write_header(AVFormatContext *s)
|
||||||
{
|
{
|
||||||
AVIContext *avi;
|
AVIContext *avi;
|
||||||
@ -247,7 +220,10 @@ static int avi_write_header(AVFormatContext *s)
|
|||||||
put_bmp_header(pb, stream);
|
put_bmp_header(pb, stream);
|
||||||
break;
|
break;
|
||||||
case CODEC_TYPE_AUDIO:
|
case CODEC_TYPE_AUDIO:
|
||||||
put_wav_header(pb, stream);
|
if (put_wav_header(pb, stream) < 0) {
|
||||||
|
free(avi);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
end_tag(pb, strf);
|
end_tag(pb, strf);
|
||||||
|
59
libav/wav.c
59
libav/wav.c
@ -19,6 +19,55 @@
|
|||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "avi.h"
|
#include "avi.h"
|
||||||
|
|
||||||
|
CodecTag codec_wav_tags[] = {
|
||||||
|
{ CODEC_ID_MP2, 0x55 },
|
||||||
|
{ CODEC_ID_MP2, 0x50 },
|
||||||
|
{ CODEC_ID_AC3, 0x2000 },
|
||||||
|
{ CODEC_ID_PCM_S16LE, 0x01 },
|
||||||
|
{ CODEC_ID_PCM_U8, 0x01 }, /* must come after s16le in this list */
|
||||||
|
{ CODEC_ID_PCM_ALAW, 0x06 },
|
||||||
|
{ CODEC_ID_PCM_MULAW, 0x07 },
|
||||||
|
{ 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* WAVEFORMATEX header */
|
||||||
|
int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
|
||||||
|
{
|
||||||
|
int tag, bps;
|
||||||
|
|
||||||
|
tag = codec_get_tag(codec_wav_tags, enc->codec_id);
|
||||||
|
if (tag == 0)
|
||||||
|
return -1;
|
||||||
|
put_le16(pb, tag);
|
||||||
|
put_le16(pb, enc->channels);
|
||||||
|
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 ||
|
||||||
|
enc->codec_id == CODEC_ID_PCM_ALAW ||
|
||||||
|
enc->codec_id == CODEC_ID_PCM_MULAW) {
|
||||||
|
bps = 8;
|
||||||
|
} else {
|
||||||
|
bps = 16;
|
||||||
|
}
|
||||||
|
put_le16(pb, bps); /* bits per sample */
|
||||||
|
|
||||||
|
put_le16(pb, 0); /* wav_extra_size */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wav_codec_get_id(unsigned int tag, int bps)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
id = codec_get_id(codec_wav_tags, tag);
|
||||||
|
if (id <= 0)
|
||||||
|
return id;
|
||||||
|
/* handle specific u8 codec */
|
||||||
|
if (id == CODEC_ID_PCM_S16LE && bps == 8)
|
||||||
|
id = CODEC_ID_PCM_U8;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
offset_t data;
|
offset_t data;
|
||||||
} WAVContext;
|
} WAVContext;
|
||||||
@ -41,7 +90,10 @@ static int wav_write_header(AVFormatContext *s)
|
|||||||
|
|
||||||
/* format header */
|
/* format header */
|
||||||
fmt = start_tag(pb, "fmt ");
|
fmt = start_tag(pb, "fmt ");
|
||||||
put_wav_header(pb, &s->streams[0]->codec);
|
if (put_wav_header(pb, &s->streams[0]->codec) < 0) {
|
||||||
|
free(wav);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
end_tag(pb, fmt);
|
end_tag(pb, fmt);
|
||||||
|
|
||||||
/* data header */
|
/* data header */
|
||||||
@ -155,12 +207,9 @@ static int wav_read_header(AVFormatContext *s,
|
|||||||
|
|
||||||
st->codec.codec_type = CODEC_TYPE_AUDIO;
|
st->codec.codec_type = CODEC_TYPE_AUDIO;
|
||||||
st->codec.codec_tag = id;
|
st->codec.codec_tag = id;
|
||||||
st->codec.codec_id = codec_get_id(codec_wav_tags, id);
|
st->codec.codec_id = wav_codec_get_id(id, bps);
|
||||||
st->codec.channels = channels;
|
st->codec.channels = channels;
|
||||||
st->codec.sample_rate = rate;
|
st->codec.sample_rate = rate;
|
||||||
if (st->codec.codec_id == CODEC_ID_PCM_S16LE && bps == 8) {
|
|
||||||
st->codec.codec_id = CODEC_ID_PCM_U8;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user