Merge remote-tracking branch 'qatar/master'

* qatar/master:
  flv: add support for G.711
  doc: git: Add checklist with test steps to perform before pushing
  flvenc: K&R formatting cosmetics
  movenc: Add channel layouts for PCM.

Conflicts:
	libavformat/flvenc.c
	tests/ref/fate/acodec-pcm-s16be
	tests/ref/fate/acodec-pcm-s24be
	tests/ref/fate/acodec-pcm-s32be
	tests/ref/fate/acodec-pcm-s8

Merged-by: Michael Niedermayer <michaelni@gmx.at>
pull/59/head
Michael Niedermayer 13 years ago
commit 4453f6b861
  1. 48
      doc/git-howto.texi
  2. 2
      libavformat/flv.h
  3. 8
      libavformat/flvdec.c
  4. 286
      libavformat/flvenc.c
  5. 26
      libavformat/mov_chan.c
  6. 2
      tests/ref/fate/acodec-pcm-s16be
  7. 2
      tests/ref/fate/acodec-pcm-s24be
  8. 2
      tests/ref/fate/acodec-pcm-s32be
  9. 2
      tests/ref/fate/acodec-pcm-s8

@ -346,6 +346,54 @@ git checkout -b svn_23456 $SHA1
where @var{$SHA1} is the commit hash from the @command{git log} output.
@chapter pre-push checklist
Once you have a set of commits that you feel are ready for pushing,
work through the following checklist to doublecheck everything is in
proper order. This list tries to be exhaustive. In case you are just
pushing a typo in a comment, some of the steps may be unnecessary.
Apply your common sense, but if in doubt, err on the side of caution.
First make sure your Git repository is on a branch that is a direct
descendant of the FFmpeg master branch, which is the only one from which
pushing to FFmpeg is possible. Then run the following command:
@itemize
@item @command{git log --patch --stat origin/master..}
to make sure that only the commits you want to push are pending, that
the log messages of the commits are correct and descriptive and contain
no cruft from @command{git am} and to doublecheck that the commits you
want to push really only contain the changes they are supposed to contain.
@item @command{git status}
to ensure no local changes still need to be committed and that no local
changes may have thrown off the results of your testing.
@end itemize
Next let the code pass through a full run of our testsuite. Before you do,
the command @command{make fate-rsync} will update the test samples. Changes
to the samples set are not very common and commits depending on samples
changes are delayed for at least 24 hours to allow the new samples to
propagate, so updating it once per day is sufficient. Now execute
@itemize
@item @command{make distclean}
@item @command{/path/to/ffmpeg/configure}
@item @command{make check}
@end itemize
While the test suite covers a wide range of possible problems, it is not
a panacea. Do not hesitate to perform any other tests necessary to convince
yourself that the changes you are about to push actually work as expected.
Also note that every single commit should pass the test suite, not just
the result of a series of patches. So if you have a series of related
commits, run the test suite on every single commit.
@chapter Server Issues
Contact the project admins @email{root@@ffmpeg.org} if you have technical

@ -94,6 +94,8 @@ enum {
FLV_CODECID_NELLYMOSER_16KHZ_MONO = 4 << FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_NELLYMOSER_8KHZ_MONO = 5 << FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_NELLYMOSER = 6 << FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_PCM_ALAW = 7 << FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_PCM_MULAW = 8 << FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_AAC = 10<< FLV_AUDIO_CODECID_OFFSET,
FLV_CODECID_SPEEX = 11<< FLV_AUDIO_CODECID_OFFSET,
};

@ -108,6 +108,14 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecCo
case FLV_CODECID_NELLYMOSER:
acodec->codec_id = CODEC_ID_NELLYMOSER;
break;
case FLV_CODECID_PCM_MULAW:
acodec->sample_rate = 8000;
acodec->codec_id = CODEC_ID_PCM_MULAW;
break;
case FLV_CODECID_PCM_ALAW:
acodec->sample_rate = 8000;
acodec->codec_id = CODEC_ID_PCM_ALAW;
break;
default:
av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;

@ -20,43 +20,45 @@
*/
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
#include "libavutil/intfloat.h"
#include "libavutil/avassert.h"
#include "avc.h"
#include "avformat.h"
#include "flv.h"
#include "internal.h"
#include "avc.h"
#include "metadata.h"
#include "libavutil/dict.h"
#include "libavutil/avassert.h"
static const AVCodecTag flv_video_codec_ids[] = {
{CODEC_ID_FLV1, FLV_CODECID_H263 },
{CODEC_ID_H263, FLV_CODECID_REALH263},
{CODEC_ID_MPEG4, FLV_CODECID_MPEG4 },
{CODEC_ID_FLASHSV, FLV_CODECID_SCREEN},
{CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2},
{CODEC_ID_VP6F, FLV_CODECID_VP6 },
{CODEC_ID_VP6, FLV_CODECID_VP6 },
{CODEC_ID_VP6A, FLV_CODECID_VP6A },
{CODEC_ID_H264, FLV_CODECID_H264 },
{CODEC_ID_NONE, 0}
{ CODEC_ID_FLV1, FLV_CODECID_H263 },
{ CODEC_ID_H263, FLV_CODECID_REALH263 },
{ CODEC_ID_MPEG4, FLV_CODECID_MPEG4 },
{ CODEC_ID_FLASHSV, FLV_CODECID_SCREEN },
{ CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2 },
{ CODEC_ID_VP6F, FLV_CODECID_VP6 },
{ CODEC_ID_VP6, FLV_CODECID_VP6 },
{ CODEC_ID_VP6A, FLV_CODECID_VP6A },
{ CODEC_ID_H264, FLV_CODECID_H264 },
{ CODEC_ID_NONE, 0 }
};
static const AVCodecTag flv_audio_codec_ids[] = {
{CODEC_ID_MP3, FLV_CODECID_MP3 >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_PCM_U8, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_PCM_S16BE, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_PCM_S16LE, FLV_CODECID_PCM_LE >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_ADPCM_SWF, FLV_CODECID_ADPCM >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_AAC, FLV_CODECID_AAC >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_NELLYMOSER, FLV_CODECID_NELLYMOSER >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_SPEEX, FLV_CODECID_SPEEX >> FLV_AUDIO_CODECID_OFFSET},
{CODEC_ID_NONE, 0}
{ CODEC_ID_MP3, FLV_CODECID_MP3 >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_PCM_U8, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_PCM_S16BE, FLV_CODECID_PCM >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_PCM_S16LE, FLV_CODECID_PCM_LE >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_ADPCM_SWF, FLV_CODECID_ADPCM >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_AAC, FLV_CODECID_AAC >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_NELLYMOSER, FLV_CODECID_NELLYMOSER >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_PCM_MULAW, FLV_CODECID_PCM_MULAW >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_PCM_ALAW, FLV_CODECID_PCM_ALAW >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_SPEEX, FLV_CODECID_SPEEX >> FLV_AUDIO_CODECID_OFFSET },
{ CODEC_ID_NONE, 0 }
};
typedef struct FLVContext {
int reserved;
int reserved;
int64_t duration_offset;
int64_t filesize_offset;
int64_t duration;
@ -69,13 +71,16 @@ typedef struct FLVStreamContext {
static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
{
int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT : FLV_SAMPLESSIZE_8BIT;
int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT
: FLV_SAMPLESSIZE_8BIT;
if (enc->codec_id == CODEC_ID_AAC) // specs force these parameters
return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | FLV_SAMPLESSIZE_16BIT | FLV_STEREO;
return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ |
FLV_SAMPLESSIZE_16BIT | FLV_STEREO;
else if (enc->codec_id == CODEC_ID_SPEEX) {
if (enc->sample_rate != 16000) {
av_log(s, AV_LOG_ERROR, "flv only supports wideband (16kHz) Speex audio\n");
av_log(s, AV_LOG_ERROR,
"flv only supports wideband (16kHz) Speex audio\n");
return -1;
}
if (enc->channels != 1) {
@ -84,34 +89,35 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
}
return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT;
} else {
switch (enc->sample_rate) {
case 44100:
switch (enc->sample_rate) {
case 44100:
flags |= FLV_SAMPLERATE_44100HZ;
break;
case 22050:
case 22050:
flags |= FLV_SAMPLERATE_22050HZ;
break;
case 11025:
case 11025:
flags |= FLV_SAMPLERATE_11025HZ;
break;
case 16000: //nellymoser only
case 8000: //nellymoser only
case 5512: //not mp3
if(enc->codec_id != CODEC_ID_MP3){
case 16000: // nellymoser only
case 8000: // nellymoser only
case 5512: // not MP3
if (enc->codec_id != CODEC_ID_MP3) {
flags |= FLV_SAMPLERATE_SPECIAL;
break;
}
default:
av_log(s, AV_LOG_ERROR, "flv does not support that sample rate, choose from (44100, 22050, 11025).\n");
av_log(s, AV_LOG_ERROR,
"flv does not support that sample rate, "
"choose from (44100, 22050, 11025).\n");
return -1;
}
}
}
if (enc->channels > 1) {
if (enc->channels > 1)
flags |= FLV_STEREO;
}
switch(enc->codec_id){
switch (enc->codec_id) {
case CODEC_ID_MP3:
flags |= FLV_CODECID_MP3 | FLV_SAMPLESSIZE_16BIT;
break;
@ -125,19 +131,24 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
flags |= FLV_CODECID_PCM_LE | FLV_SAMPLESSIZE_16BIT;
break;
case CODEC_ID_ADPCM_SWF:
flags |= FLV_CODECID_ADPCM | FLV_SAMPLESSIZE_16BIT;
flags |= FLV_CODECID_ADPCM | FLV_SAMPLESSIZE_16BIT;
break;
case CODEC_ID_NELLYMOSER:
if (enc->sample_rate == 8000) {
flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
} else if (enc->sample_rate == 16000) {
if (enc->sample_rate == 8000)
flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
else if (enc->sample_rate == 16000)
flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
} else {
flags |= FLV_CODECID_NELLYMOSER | FLV_SAMPLESSIZE_16BIT;
}
else
flags |= FLV_CODECID_NELLYMOSER | FLV_SAMPLESSIZE_16BIT;
break;
case CODEC_ID_PCM_MULAW:
flags = FLV_CODECID_PCM_MULAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
break;
case CODEC_ID_PCM_ALAW:
flags = FLV_CODECID_PCM_ALAW | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
break;
case 0:
flags |= enc->codec_tag<<4;
flags |= enc->codec_tag << 4;
break;
default:
av_log(s, AV_LOG_ERROR, "codec not compatible with flv\n");
@ -154,16 +165,17 @@ static void put_amf_string(AVIOContext *pb, const char *str)
avio_write(pb, str, len);
}
static void put_avc_eos_tag(AVIOContext *pb, unsigned ts) {
static void put_avc_eos_tag(AVIOContext *pb, unsigned ts)
{
avio_w8(pb, FLV_TAG_TYPE_VIDEO);
avio_wb24(pb, 5); /* Tag Data Size */
avio_wb24(pb, ts); /* lower 24 bits of timestamp in ms*/
avio_w8(pb, (ts >> 24) & 0x7F); /* MSB of ts in ms*/
avio_wb24(pb, 0); /* StreamId = 0 */
avio_w8(pb, 23); /* ub[4] FrameType = 1, ub[4] CodecId = 7 */
avio_w8(pb, 2); /* AVC end of sequence */
avio_wb24(pb, 0); /* Always 0 for AVC EOS. */
avio_wb32(pb, 16); /* Size of FLV tag */
avio_wb24(pb, 5); /* Tag Data Size */
avio_wb24(pb, ts); /* lower 24 bits of timestamp in ms */
avio_w8(pb, (ts >> 24) & 0x7F); /* MSB of ts in ms */
avio_wb24(pb, 0); /* StreamId = 0 */
avio_w8(pb, 23); /* ub[4] FrameType = 1, ub[4] CodecId = 7 */
avio_w8(pb, 2); /* AVC end of sequence */
avio_wb24(pb, 0); /* Always 0 for AVC EOS. */
avio_wb32(pb, 16); /* Size of FLV tag */
}
static void put_amf_double(AVIOContext *pb, double d)
@ -172,7 +184,8 @@ static void put_amf_double(AVIOContext *pb, double d)
avio_wb64(pb, av_double2int(d));
}
static void put_amf_bool(AVIOContext *pb, int b) {
static void put_amf_bool(AVIOContext *pb, int b)
{
avio_w8(pb, AMF_DATA_TYPE_BOOL);
avio_w8(pb, !!b);
}
@ -187,18 +200,19 @@ static int flv_write_header(AVFormatContext *s)
int64_t metadata_size_pos, data_size, metadata_count_pos;
AVDictionaryEntry *tag = NULL;
for(i=0; i<s->nb_streams; i++){
for (i = 0; i < s->nb_streams; i++) {
AVCodecContext *enc = s->streams[i]->codec;
FLVStreamContext *sc;
switch (enc->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) {
if (s->streams[i]->r_frame_rate.den &&
s->streams[i]->r_frame_rate.num) {
framerate = av_q2d(s->streams[i]->r_frame_rate);
} else {
framerate = 1/av_q2d(s->streams[i]->codec->time_base);
framerate = 1 / av_q2d(s->streams[i]->codec->time_base);
}
video_enc = enc;
if(enc->codec_tag == 0) {
if (enc->codec_tag == 0) {
av_log(s, AV_LOG_ERROR, "video codec not compatible with flv\n");
return -1;
}
@ -227,32 +241,32 @@ static int flv_write_header(AVFormatContext *s)
s->streams[i]->priv_data = sc;
sc->last_ts = -1;
}
flv->delay = AV_NOPTS_VALUE;
avio_write(pb, "FLV", 3);
avio_w8(pb,1);
avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc
+ FLV_HEADER_FLAG_HASVIDEO * !!video_enc);
avio_wb32(pb,9);
avio_wb32(pb,0);
for(i=0; i<s->nb_streams; i++){
if(s->streams[i]->codec->codec_tag == 5){
avio_w8(pb,8); // message type
avio_wb24(pb,0); // include flags
avio_wb24(pb,0); // time stamp
avio_wb32(pb,0); // reserved
avio_wb32(pb,11); // size
flv->reserved=5;
avio_w8(pb, 1);
avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc +
FLV_HEADER_FLAG_HASVIDEO * !!video_enc);
avio_wb32(pb, 9);
avio_wb32(pb, 0);
for (i = 0; i < s->nb_streams; i++)
if (s->streams[i]->codec->codec_tag == 5) {
avio_w8(pb, 8); // message type
avio_wb24(pb, 0); // include flags
avio_wb24(pb, 0); // time stamp
avio_wb32(pb, 0); // reserved
avio_wb32(pb, 11); // size
flv->reserved = 5;
}
}
/* write meta_tag */
avio_w8(pb, 18); // tag type META
metadata_size_pos= avio_tell(pb);
avio_wb24(pb, 0); // size of data part (sum of all parts below)
avio_wb24(pb, 0); // time stamp
avio_wb32(pb, 0); // reserved
avio_w8(pb, 18); // tag type META
metadata_size_pos = avio_tell(pb);
avio_wb24(pb, 0); // size of data part (sum of all parts below)
avio_wb24(pb, 0); // timestamp
avio_wb32(pb, 0); // reserved
/* now data of data_size size */
@ -265,16 +279,18 @@ static int flv_write_header(AVFormatContext *s)
metadata_count_pos = avio_tell(pb);
metadata_count = 5 * !!video_enc +
5 * !!audio_enc +
1 * !!data_enc +
1 * !!data_enc +
2; // +2 for duration and file size
avio_wb32(pb, metadata_count);
put_amf_string(pb, "duration");
flv->duration_offset= avio_tell(pb);
put_amf_double(pb, s->duration / AV_TIME_BASE); // fill in the guessed duration, it'll be corrected later if incorrect
if(video_enc){
// fill in the guessed duration, it'll be corrected later if incorrect
put_amf_double(pb, s->duration / AV_TIME_BASE);
if (video_enc) {
put_amf_string(pb, "width");
put_amf_double(pb, video_enc->width);
@ -291,7 +307,7 @@ static int flv_write_header(AVFormatContext *s)
put_amf_double(pb, video_enc->codec_tag);
}
if(audio_enc){
if (audio_enc) {
put_amf_string(pb, "audiodatarate");
put_amf_double(pb, audio_enc->bit_rate / 1024.0);
@ -337,14 +353,14 @@ static int flv_write_header(AVFormatContext *s)
}
put_amf_string(pb, "filesize");
flv->filesize_offset= avio_tell(pb);
flv->filesize_offset = avio_tell(pb);
put_amf_double(pb, 0); // delayed write
put_amf_string(pb, "");
avio_w8(pb, AMF_END_OF_OBJECT);
/* write total size of tag */
data_size= avio_tell(pb) - metadata_size_pos - 10;
data_size = avio_tell(pb) - metadata_size_pos - 10;
avio_seek(pb, metadata_count_pos, SEEK_SET);
avio_wb32(pb, metadata_count);
@ -359,10 +375,10 @@ static int flv_write_header(AVFormatContext *s)
if (enc->codec_id == CODEC_ID_AAC || enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) {
int64_t pos;
avio_w8(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO ?
FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO);
FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO);
avio_wb24(pb, 0); // size patched later
avio_wb24(pb, 0); // ts
avio_w8(pb, 0); // ts ext
avio_w8(pb, 0); // ts ext
avio_wb24(pb, 0); // streamid
pos = avio_tell(pb);
if (enc->codec_id == CODEC_ID_AAC) {
@ -399,9 +415,8 @@ static int flv_write_trailer(AVFormatContext *s)
AVCodecContext *enc = s->streams[i]->codec;
FLVStreamContext *sc = s->streams[i]->priv_data;
if (enc->codec_type == AVMEDIA_TYPE_VIDEO &&
(enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4)) {
(enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4))
put_avc_eos_tag(pb, sc->last_ts);
}
}
file_size = avio_tell(pb);
@ -418,32 +433,35 @@ static int flv_write_trailer(AVFormatContext *s)
static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIOContext *pb = s->pb;
AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
FLVContext *flv = s->priv_data;
AVIOContext *pb = s->pb;
AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
FLVContext *flv = s->priv_data;
FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data;
unsigned ts;
int size= pkt->size;
uint8_t *data= NULL;
int size = pkt->size;
uint8_t *data = NULL;
int flags, flags_size;
// av_log(s, AV_LOG_DEBUG, "type:%d pts: %"PRId64" size:%d\n", enc->codec_type, timestamp, size);
// av_log(s, AV_LOG_DEBUG, "type:%d pts: %"PRId64" size:%d\n",
// enc->codec_type, timestamp, size);
if(enc->codec_id == CODEC_ID_VP6 || enc->codec_id == CODEC_ID_VP6F ||
enc->codec_id == CODEC_ID_VP6A || enc->codec_id == CODEC_ID_AAC)
flags_size= 2;
else if(enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4)
flags_size= 5;
if (enc->codec_id == CODEC_ID_VP6 || enc->codec_id == CODEC_ID_VP6F ||
enc->codec_id == CODEC_ID_VP6A || enc->codec_id == CODEC_ID_AAC)
flags_size = 2;
else if (enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4)
flags_size = 5;
else
flags_size= 1;
flags_size = 1;
switch (enc->codec_type) {
case AVMEDIA_TYPE_VIDEO:
avio_w8(pb, FLV_TAG_TYPE_VIDEO);
flags = enc->codec_tag;
if(flags == 0) {
av_log(s, AV_LOG_ERROR, "video codec %s not compatible with flv\n", avcodec_get_name(enc->codec_id));
if (flags == 0) {
av_log(s, AV_LOG_ERROR,
"video codec %s not compatible with flv\n",
avcodec_get_name(enc->codec_id));
return -1;
}
@ -462,41 +480,42 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
default:
return AVERROR(EINVAL);
}
if (enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) {
/* check if extradata looks like mp4 formated */
if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) {
if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1)
if (ff_avc_parse_nal_units_buf(pkt->data, &data, &size) < 0)
return -1;
}
} else if (enc->codec_id == CODEC_ID_AAC && pkt->size > 2 &&
(AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n");
return -1;
}
if (flv->delay == AV_NOPTS_VALUE)
flv->delay = -pkt->dts;
if (pkt->dts < -flv->delay) {
av_log(s, AV_LOG_WARNING, "Packets are not in the proper order with "
"respect to DTS\n");
av_log(s, AV_LOG_WARNING,
"Packets are not in the proper order with respect to DTS\n");
return AVERROR(EINVAL);
}
ts = pkt->dts + flv->delay; // add delay to force positive dts
/* check Speex packet duration */
if (enc->codec_id == CODEC_ID_SPEEX && ts - sc->last_ts > 160) {
if (enc->codec_id == CODEC_ID_SPEEX && ts - sc->last_ts > 160)
av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "
"8 frames per packet. Adobe Flash "
"Player cannot handle this!\n");
}
if (sc->last_ts < ts)
sc->last_ts = ts;
avio_wb24(pb,size + flags_size);
avio_wb24(pb,ts);
avio_w8(pb,(ts >> 24) & 0x7F); // timestamps are 32bits _signed_
avio_wb24(pb,flv->reserved);
avio_wb24(pb, size + flags_size);
avio_wb24(pb, ts);
avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_
avio_wb24(pb, flv->reserved);
if (enc->codec_type == AVMEDIA_TYPE_DATA) {
int data_size;
@ -520,25 +539,26 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
avio_seek(pb, data_size + 10 - 3, SEEK_CUR);
avio_wb32(pb, data_size + 11);
} else {
avio_w8(pb,flags);
if (enc->codec_id == CODEC_ID_VP6)
avio_w8(pb,0);
if (enc->codec_id == CODEC_ID_VP6F || enc->codec_id == CODEC_ID_VP6A)
avio_w8(pb, enc->extradata_size ? enc->extradata[0] : 0);
else if (enc->codec_id == CODEC_ID_AAC)
avio_w8(pb,1); // AAC raw
else if (enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) {
avio_w8(pb,1); // AVC NALU
avio_wb24(pb,pkt->pts - pkt->dts);
}
avio_w8(pb,flags);
if (enc->codec_id == CODEC_ID_VP6)
avio_w8(pb,0);
if (enc->codec_id == CODEC_ID_VP6F || enc->codec_id == CODEC_ID_VP6A)
avio_w8(pb, enc->extradata_size ? enc->extradata[0] : 0);
else if (enc->codec_id == CODEC_ID_AAC)
avio_w8(pb,1); // AAC raw
else if (enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) {
avio_w8(pb,1); // AVC NALU
avio_wb24(pb,pkt->pts - pkt->dts);
}
avio_write(pb, data ? data : pkt->data, size);
avio_write(pb, data ? data : pkt->data, size);
avio_wb32(pb,size+flags_size+11); // previous tag size
flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration);
avio_wb32(pb, size + flags_size + 11); // previous tag size
flv->duration = FFMAX(flv->duration,
pkt->pts + flv->delay + pkt->duration);
}
avio_flush(pb);
avio_flush(pb);
av_free(data);
return pb->error;
@ -559,9 +579,9 @@ AVOutputFormat ff_flv_muxer = {
.write_header = flv_write_header,
.write_packet = flv_write_packet,
.write_trailer = flv_write_trailer,
.codec_tag = (const AVCodecTag* const []){
flv_video_codec_ids, flv_audio_codec_ids, 0
},
.codec_tag = (const AVCodecTag* const []) {
flv_video_codec_ids, flv_audio_codec_ids, 0
},
.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
AVFMT_TS_NONSTRICT,
};

@ -414,6 +414,20 @@ static const enum MovChannelLayoutTag mov_ch_layouts_alac[] = {
0,
};
static const enum MovChannelLayoutTag mov_ch_layouts_wav[] = {
MOV_CH_LAYOUT_MONO,
MOV_CH_LAYOUT_STEREO,
MOV_CH_LAYOUT_MATRIXSTEREO,
MOV_CH_LAYOUT_MPEG_3_0_A,
MOV_CH_LAYOUT_QUADRAPHONIC,
MOV_CH_LAYOUT_MPEG_5_0_A,
MOV_CH_LAYOUT_MPEG_5_1_A,
MOV_CH_LAYOUT_MPEG_6_1_A,
MOV_CH_LAYOUT_MPEG_7_1_A,
MOV_CH_LAYOUT_MPEG_7_1_C,
MOV_CH_LAYOUT_SMPTE_DTV,
};
static const struct {
enum CodecID codec_id;
const enum MovChannelLayoutTag *layouts;
@ -421,6 +435,18 @@ static const struct {
{ CODEC_ID_AAC, mov_ch_layouts_aac },
{ CODEC_ID_AC3, mov_ch_layouts_ac3 },
{ CODEC_ID_ALAC, mov_ch_layouts_alac },
{ CODEC_ID_PCM_U8, mov_ch_layouts_wav },
{ CODEC_ID_PCM_S8, mov_ch_layouts_wav },
{ CODEC_ID_PCM_S16LE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_S16BE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_S24LE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_S24BE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_S32LE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_S32BE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_F32LE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_F32BE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_F64LE, mov_ch_layouts_wav },
{ CODEC_ID_PCM_F64BE, mov_ch_layouts_wav },
{ CODEC_ID_NONE, NULL },
};

@ -1,4 +1,4 @@
8bffa66afe9e17366af11e77882518a0 *tests/data/fate/acodec-pcm-s16be.mov
d00ca427a66be2e33ca8d63bcde41316 *tests/data/fate/acodec-pcm-s16be.mov
1059069 tests/data/fate/acodec-pcm-s16be.mov
64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s16be.out.wav
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400

@ -1,4 +1,4 @@
e3013cfce9b792acb9d572268012160d *tests/data/fate/acodec-pcm-s24be.mov
5d843e1f56796aae3185016f164b16b7 *tests/data/fate/acodec-pcm-s24be.mov
1588269 tests/data/fate/acodec-pcm-s24be.mov
64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s24be.out.wav
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400

@ -1,4 +1,4 @@
f3ef00480e89c5c791e87b8af1cc167c *tests/data/fate/acodec-pcm-s32be.mov
b34c66c56df1b1e75688929cf20670b9 *tests/data/fate/acodec-pcm-s32be.mov
2117473 tests/data/fate/acodec-pcm-s32be.mov
64151e4bcc2b717aa5a8454d424d6a1f *tests/data/fate/acodec-pcm-s32be.out.wav
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400

@ -1,4 +1,4 @@
2c504a4e48c19ea1b0e1705893b771bf *tests/data/fate/acodec-pcm-s8.mov
d931dc4fffa2d3398e0f31f97e7d6c3a *tests/data/fate/acodec-pcm-s8.mov
529853 tests/data/fate/acodec-pcm-s8.mov
651d4eb8d98dfcdda96ae6c43d8f156b *tests/data/fate/acodec-pcm-s8.out.wav
stddev: 147.89 PSNR: 52.93 MAXDIFF: 255 bytes: 1058400/ 1058400

Loading…
Cancel
Save