summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/internal.h15
-rw-r--r--libavformat/mov.c33
-rw-r--r--libavformat/nuv.c23
-rw-r--r--libavformat/riff.c21
-rw-r--r--libavformat/utils.c31
5 files changed, 78 insertions, 45 deletions
diff --git a/libavformat/internal.h b/libavformat/internal.h
index 4f740c99d1..14f4cdbdf1 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -360,6 +360,21 @@ unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id);
enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag);
/**
+ * Select a PCM codec based on the given parameters.
+ *
+ * @param bps bits-per-sample
+ * @param flt floating-point
+ * @param be big-endian
+ * @param sflags signed flags. each bit corresponds to one byte of bit depth.
+ * e.g. the 1st bit indicates if 8-bit should be signed or
+ * unsigned, the 2nd bit indicates if 16-bit should be signed or
+ * unsigned, etc... This is useful for formats such as WAVE where
+ * only 8-bit is unsigned and all other bit depths are signed.
+ * @return a PCM codec id or AV_CODEC_ID_NONE
+ */
+enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags);
+
+/**
* Chooses a timebase for muxing the specified stream.
*
* The choosen timebase allows sample accurate timestamps based
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 1a8a5a7182..149bd20954 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1170,33 +1170,12 @@ static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
*/
enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags)
{
- if (flags & 1) { // floating point
- if (flags & 2) { // big endian
- if (bps == 32) return AV_CODEC_ID_PCM_F32BE;
- else if (bps == 64) return AV_CODEC_ID_PCM_F64BE;
- } else {
- if (bps == 32) return AV_CODEC_ID_PCM_F32LE;
- else if (bps == 64) return AV_CODEC_ID_PCM_F64LE;
- }
- } else {
- if (flags & 2) {
- if (bps == 8) {
- // signed integer
- if (flags & 4) return AV_CODEC_ID_PCM_S8;
- else return AV_CODEC_ID_PCM_U8;
- }else if (bps == 16) return AV_CODEC_ID_PCM_S16BE;
- else if (bps == 24) return AV_CODEC_ID_PCM_S24BE;
- else if (bps == 32) return AV_CODEC_ID_PCM_S32BE;
- } else {
- if (bps == 8) {
- if (flags & 4) return AV_CODEC_ID_PCM_S8;
- else return AV_CODEC_ID_PCM_U8;
- }else if (bps == 16) return AV_CODEC_ID_PCM_S16LE;
- else if (bps == 24) return AV_CODEC_ID_PCM_S24LE;
- else if (bps == 32) return AV_CODEC_ID_PCM_S32LE;
- }
- }
- return AV_CODEC_ID_NONE;
+ /* lpcm flags:
+ * 0x1 = float
+ * 0x2 = big-endian
+ * 0x4 = signed
+ */
+ return ff_get_pcm_codec_id(bps, flags & 1, flags & 2, flags & 4 ? -1 : 0);
}
int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
diff --git a/libavformat/nuv.c b/libavformat/nuv.c
index c67c1fa695..37d92e284f 100644
--- a/libavformat/nuv.c
+++ b/libavformat/nuv.c
@@ -26,6 +26,12 @@
#include "internal.h"
#include "riff.h"
+static const AVCodecTag nuv_audio_tags[] = {
+ { AV_CODEC_ID_PCM_S16LE, MKTAG('R', 'A', 'W', 'A') },
+ { AV_CODEC_ID_MP3, MKTAG('L', 'A', 'M', 'E') },
+ { AV_CODEC_ID_NONE, 0 },
+};
+
typedef struct {
int v_id;
int a_id;
@@ -96,14 +102,25 @@ static int get_codec_data(AVIOContext *pb, AVStream *vst,
avio_skip(pb, 4);
if (ast) {
+ int id;
+
ast->codec->codec_tag = avio_rl32(pb);
ast->codec->sample_rate = avio_rl32(pb);
ast->codec->bits_per_coded_sample = avio_rl32(pb);
ast->codec->channels = avio_rl32(pb);
ast->codec->channel_layout = 0;
- ast->codec->codec_id =
- ff_wav_codec_get_id(ast->codec->codec_tag,
- ast->codec->bits_per_coded_sample);
+
+ id = ff_wav_codec_get_id(ast->codec->codec_tag,
+ ast->codec->bits_per_coded_sample);
+ if (id == AV_CODEC_ID_NONE) {
+ id = ff_codec_get_id(nuv_audio_tags,
+ ast->codec->codec_tag);
+ if (id == AV_CODEC_ID_PCM_S16LE)
+ id = ff_get_pcm_codec_id(ast->codec->bits_per_coded_sample,
+ 0, 0, ~1);
+ }
+ ast->codec->codec_id = id;
+
ast->need_parsing = AVSTREAM_PARSE_FULL;
} else
avio_skip(pb, 4 * 4);
diff --git a/libavformat/riff.c b/libavformat/riff.c
index cddbec477c..57d6ca68df 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -384,11 +384,6 @@ const AVCodecTag ff_codec_wav_tags[] = {
{ AV_CODEC_ID_FLAC, 0xF1AC },
{ AV_CODEC_ID_ADPCM_SWF, ('S'<<8)+'F' },
{ AV_CODEC_ID_VORBIS, ('V'<<8)+'o' }, //HACK/FIXME, does vorbis in WAV/AVI have an (in)official id?
-
- /* FIXME: All of the IDs below are not 16 bit and thus illegal. */
- // for NuppelVideo (nuv.c)
- { AV_CODEC_ID_PCM_S16LE, MKTAG('R', 'A', 'W', 'A') },
- { AV_CODEC_ID_MP3, MKTAG('L', 'A', 'M', 'E') },
{ AV_CODEC_ID_NONE, 0 },
};
@@ -757,16 +752,12 @@ enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps)
id = ff_codec_get_id(ff_codec_wav_tags, tag);
if (id <= 0)
return id;
- /* handle specific u8 codec */
- if (id == AV_CODEC_ID_PCM_S16LE && bps == 8)
- id = AV_CODEC_ID_PCM_U8;
- if (id == AV_CODEC_ID_PCM_S16LE && bps == 20 ||
- id == AV_CODEC_ID_PCM_S16LE && bps == 24)
- id = AV_CODEC_ID_PCM_S24LE;
- if (id == AV_CODEC_ID_PCM_S16LE && bps == 32)
- id = AV_CODEC_ID_PCM_S32LE;
- if (id == AV_CODEC_ID_PCM_F32LE && bps == 64)
- id = AV_CODEC_ID_PCM_F64LE;
+
+ if (id == AV_CODEC_ID_PCM_S16LE)
+ id = ff_get_pcm_codec_id(bps, 0, 0, ~1);
+ else if (id == AV_CODEC_ID_PCM_F32LE)
+ id = ff_get_pcm_codec_id(bps, 1, 0, 0);
+
if (id == AV_CODEC_ID_ADPCM_IMA_WAV && bps == 8)
id = AV_CODEC_ID_PCM_ZORK;
return id;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 3e87dbc76e..b7506dea98 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2440,6 +2440,37 @@ enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
return AV_CODEC_ID_NONE;
}
+enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags)
+{
+ if (flt) {
+ switch (bps) {
+ case 32: return be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
+ case 64: return be ? AV_CODEC_ID_PCM_F64BE : AV_CODEC_ID_PCM_F64LE;
+ default: return AV_CODEC_ID_NONE;
+ }
+ } else {
+ bps += 7;
+ bps >>= 3;
+ if (sflags & (1 << (bps - 1))) {
+ switch (bps) {
+ case 1: return AV_CODEC_ID_PCM_S8;
+ case 2: return be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
+ case 3: return be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
+ case 4: return be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
+ default: return AV_CODEC_ID_NONE;
+ }
+ } else {
+ switch (bps) {
+ case 1: return AV_CODEC_ID_PCM_U8;
+ case 2: return be ? AV_CODEC_ID_PCM_U16BE : AV_CODEC_ID_PCM_U16LE;
+ case 3: return be ? AV_CODEC_ID_PCM_U24BE : AV_CODEC_ID_PCM_U24LE;
+ case 4: return be ? AV_CODEC_ID_PCM_U32BE : AV_CODEC_ID_PCM_U32LE;
+ default: return AV_CODEC_ID_NONE;
+ }
+ }
+ }
+}
+
unsigned int av_codec_get_tag(const AVCodecTag * const *tags, enum AVCodecID id)
{
int i;