update version string in changelog
Originally committed as revision 23114 to svn://svn.ffmpeg.org/ffmpeg/branches/0.6
This commit is contained in:
parent
ddb630177a
commit
64c2076bfc
@ -2,7 +2,7 @@ Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
|
||||
version <next>:
|
||||
version 0.6:
|
||||
|
||||
- PB-frame decoding for H.263
|
||||
- deprecated vhook subsystem removed
|
||||
|
@ -219,36 +219,6 @@ static int mov_read_udta_string(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mov_read_chpl(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
||||
{
|
||||
int64_t start;
|
||||
int i, nb_chapters, str_len;
|
||||
char str[256+1];
|
||||
|
||||
if ((atom.size -= 5) < 0)
|
||||
return 0;
|
||||
|
||||
get_be32(pb); // version + flags
|
||||
get_be32(pb); // ???
|
||||
nb_chapters = get_byte(pb);
|
||||
|
||||
for (i = 0; i < nb_chapters; i++) {
|
||||
if (atom.size < 9)
|
||||
return 0;
|
||||
|
||||
start = get_be64(pb);
|
||||
str_len = get_byte(pb);
|
||||
|
||||
if ((atom.size -= 9+str_len) < 0)
|
||||
return 0;
|
||||
|
||||
get_buffer(pb, str, str_len);
|
||||
str[str_len] = 0;
|
||||
ff_new_chapter(c->fc, i, (AVRational){1,10000000}, start, AV_NOPTS_VALUE, str);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
||||
{
|
||||
int64_t total_size = 0;
|
||||
@ -2196,7 +2166,6 @@ static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
||||
|
||||
static const MOVParseTableEntry mov_default_parse_table[] = {
|
||||
{ MKTAG('a','v','s','s'), mov_read_extradata },
|
||||
{ MKTAG('c','h','p','l'), mov_read_chpl },
|
||||
{ MKTAG('c','o','6','4'), mov_read_stco },
|
||||
{ MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */
|
||||
{ MKTAG('d','i','n','f'), mov_read_default },
|
||||
|
@ -77,15 +77,12 @@ typedef struct MOVIndex {
|
||||
MOVIentry *cluster;
|
||||
int audio_vbr;
|
||||
int height; ///< active picture (w/o VBI) height for D-10/IMX
|
||||
uint32_t tref_tag;
|
||||
int tref_id; ///< trackID of the referenced track
|
||||
} MOVTrack;
|
||||
|
||||
typedef struct MOVMuxContext {
|
||||
int mode;
|
||||
int64_t time;
|
||||
int nb_streams;
|
||||
int chapter_track; ///< qt chapter track number
|
||||
int64_t mdat_pos;
|
||||
uint64_t mdat_size;
|
||||
MOVTrack *tracks;
|
||||
@ -1186,8 +1183,8 @@ static int mov_write_tkhd_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
|
||||
put_be32(pb, 0x40000000); /* reserved */
|
||||
|
||||
/* Track width and height, for visual only */
|
||||
if(st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
|
||||
track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
|
||||
if(track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
|
||||
track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
|
||||
double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
|
||||
if(!sample_aspect_ratio || track->height != track->enc->height)
|
||||
sample_aspect_ratio = 1;
|
||||
@ -1220,16 +1217,6 @@ static int mov_write_edts_tag(ByteIOContext *pb, MOVTrack *track)
|
||||
return 0x24;
|
||||
}
|
||||
|
||||
static int mov_write_tref_tag(ByteIOContext *pb, MOVTrack *track)
|
||||
{
|
||||
put_be32(pb, 20); // size
|
||||
put_tag(pb, "tref");
|
||||
put_be32(pb, 12); // size (subatom)
|
||||
put_le32(pb, track->tref_tag);
|
||||
put_be32(pb, track->tref_id);
|
||||
return 20;
|
||||
}
|
||||
|
||||
// goes at the end of each track! ... Critical for PSP playback ("Incompatible data" without it)
|
||||
static int mov_write_uuid_tag_psp(ByteIOContext *pb, MOVTrack *mov)
|
||||
{
|
||||
@ -1257,8 +1244,6 @@ static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
|
||||
mov_write_tkhd_tag(pb, track, st);
|
||||
if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS)
|
||||
mov_write_edts_tag(pb, track); // PSP Movies require edts box
|
||||
if (track->tref_tag)
|
||||
mov_write_tref_tag(pb, track);
|
||||
mov_write_mdia_tag(pb, track);
|
||||
if (track->mode == MODE_PSP)
|
||||
mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box
|
||||
@ -1671,17 +1656,11 @@ static int mov_write_moov_tag(ByteIOContext *pb, MOVMuxContext *mov,
|
||||
mov->tracks[i].trackID = i+1;
|
||||
}
|
||||
|
||||
if (mov->chapter_track)
|
||||
for (i=0; i<s->nb_streams; i++) {
|
||||
mov->tracks[i].tref_tag = MKTAG('c','h','a','p');
|
||||
mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].trackID;
|
||||
}
|
||||
|
||||
mov_write_mvhd_tag(pb, mov);
|
||||
//mov_write_iods_tag(pb, mov);
|
||||
for (i=0; i<mov->nb_streams; i++) {
|
||||
if(mov->tracks[i].entry > 0) {
|
||||
mov_write_trak_tag(pb, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
|
||||
mov_write_trak_tag(pb, &(mov->tracks[i]), s->streams[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1822,6 +1801,117 @@ static void mov_write_uuidprof_tag(ByteIOContext *pb, AVFormatContext *s)
|
||||
put_be32(pb, 0x010001); /* ? */
|
||||
}
|
||||
|
||||
static int mov_write_header(AVFormatContext *s)
|
||||
{
|
||||
ByteIOContext *pb = s->pb;
|
||||
MOVMuxContext *mov = s->priv_data;
|
||||
int i;
|
||||
|
||||
if (url_is_streamed(s->pb)) {
|
||||
av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Default mode == MP4 */
|
||||
mov->mode = MODE_MP4;
|
||||
|
||||
if (s->oformat != NULL) {
|
||||
if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
|
||||
else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
|
||||
else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
|
||||
else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
|
||||
else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
|
||||
|
||||
mov_write_ftyp_tag(pb,s);
|
||||
if (mov->mode == MODE_PSP) {
|
||||
if (s->nb_streams != 2) {
|
||||
av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
|
||||
return -1;
|
||||
}
|
||||
mov_write_uuidprof_tag(pb,s);
|
||||
}
|
||||
}
|
||||
|
||||
mov->tracks = av_mallocz(s->nb_streams*sizeof(*mov->tracks));
|
||||
if (!mov->tracks)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for(i=0; i<s->nb_streams; i++){
|
||||
AVStream *st= s->streams[i];
|
||||
MOVTrack *track= &mov->tracks[i];
|
||||
AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL,0);
|
||||
|
||||
track->enc = st->codec;
|
||||
track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
|
||||
if (track->language < 0)
|
||||
track->language = 0;
|
||||
track->mode = mov->mode;
|
||||
track->tag = mov_find_codec_tag(s, track);
|
||||
if (!track->tag) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
|
||||
"codec not currently supported in container\n", i);
|
||||
goto error;
|
||||
}
|
||||
if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
|
||||
if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
|
||||
track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
|
||||
track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
|
||||
if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
|
||||
av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
|
||||
goto error;
|
||||
}
|
||||
track->height = track->tag>>24 == 'n' ? 486 : 576;
|
||||
}
|
||||
track->timescale = st->codec->time_base.den;
|
||||
if (track->mode == MODE_MOV && track->timescale > 100000)
|
||||
av_log(s, AV_LOG_WARNING,
|
||||
"WARNING codec timebase is very high. If duration is too long,\n"
|
||||
"file may not be playable by quicktime. Specify a shorter timebase\n"
|
||||
"or choose different container.\n");
|
||||
}else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
|
||||
track->timescale = st->codec->sample_rate;
|
||||
if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
|
||||
goto error;
|
||||
}else if(st->codec->frame_size > 1){ /* assume compressed audio */
|
||||
track->audio_vbr = 1;
|
||||
}else{
|
||||
st->codec->frame_size = 1;
|
||||
track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
|
||||
}
|
||||
if (track->mode != MODE_MOV) {
|
||||
if (track->timescale > UINT16_MAX) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: output format does not support "
|
||||
"sample rate %dhz\n", i, track->timescale);
|
||||
goto error;
|
||||
}
|
||||
if (track->enc->codec_id == CODEC_ID_MP3 && track->timescale < 16000) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
|
||||
i, track->enc->sample_rate);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}else if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE){
|
||||
track->timescale = st->codec->time_base.den;
|
||||
}
|
||||
if (!track->height)
|
||||
track->height = st->codec->height;
|
||||
|
||||
av_set_pts_info(st, 64, 1, track->timescale);
|
||||
}
|
||||
|
||||
mov_write_mdat_tag(pb, mov);
|
||||
mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
|
||||
mov->nb_streams = s->nb_streams;
|
||||
|
||||
put_flush_packet(pb);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
av_freep(&mov->tracks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags)
|
||||
{
|
||||
uint32_t c = -1;
|
||||
@ -1939,158 +2029,6 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// QuickTime chapters involve an additional text track with the chapter names
|
||||
// as samples, and a tref pointing from the other tracks to the chapter one.
|
||||
static void mov_create_chapter_track(AVFormatContext *s, int tracknum)
|
||||
{
|
||||
MOVMuxContext *mov = s->priv_data;
|
||||
MOVTrack *track = &mov->tracks[tracknum];
|
||||
AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY };
|
||||
int i, len;
|
||||
|
||||
track->mode = mov->mode;
|
||||
track->tag = MKTAG('t','e','x','t');
|
||||
track->timescale = MOV_TIMESCALE;
|
||||
track->enc = avcodec_alloc_context();
|
||||
track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
|
||||
|
||||
for (i = 0; i < s->nb_chapters; i++) {
|
||||
AVChapter *c = s->chapters[i];
|
||||
AVMetadataTag *t;
|
||||
|
||||
int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE});
|
||||
pkt.pts = pkt.dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE});
|
||||
pkt.duration = end - pkt.dts;
|
||||
|
||||
if ((t = av_metadata_get(c->metadata, "title", NULL, 0))) {
|
||||
len = strlen(t->value);
|
||||
pkt.size = len+2;
|
||||
pkt.data = av_malloc(pkt.size);
|
||||
AV_WB16(pkt.data, len);
|
||||
memcpy(pkt.data+2, t->value, len);
|
||||
mov_write_packet(s, &pkt);
|
||||
av_freep(&pkt.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mov_write_header(AVFormatContext *s)
|
||||
{
|
||||
ByteIOContext *pb = s->pb;
|
||||
MOVMuxContext *mov = s->priv_data;
|
||||
int i;
|
||||
|
||||
if (url_is_streamed(s->pb)) {
|
||||
av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Default mode == MP4 */
|
||||
mov->mode = MODE_MP4;
|
||||
|
||||
if (s->oformat != NULL) {
|
||||
if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP;
|
||||
else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2;
|
||||
else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV;
|
||||
else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP;
|
||||
else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD;
|
||||
|
||||
mov_write_ftyp_tag(pb,s);
|
||||
if (mov->mode == MODE_PSP) {
|
||||
if (s->nb_streams != 2) {
|
||||
av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n");
|
||||
return -1;
|
||||
}
|
||||
mov_write_uuidprof_tag(pb,s);
|
||||
}
|
||||
}
|
||||
|
||||
mov->nb_streams = s->nb_streams;
|
||||
if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters)
|
||||
mov->chapter_track = mov->nb_streams++;
|
||||
|
||||
mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks));
|
||||
if (!mov->tracks)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
for(i=0; i<s->nb_streams; i++){
|
||||
AVStream *st= s->streams[i];
|
||||
MOVTrack *track= &mov->tracks[i];
|
||||
AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL,0);
|
||||
|
||||
track->enc = st->codec;
|
||||
track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
|
||||
if (track->language < 0)
|
||||
track->language = 0;
|
||||
track->mode = mov->mode;
|
||||
track->tag = mov_find_codec_tag(s, track);
|
||||
if (!track->tag) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: could not find tag, "
|
||||
"codec not currently supported in container\n", i);
|
||||
goto error;
|
||||
}
|
||||
if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
|
||||
if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
|
||||
track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
|
||||
track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
|
||||
if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
|
||||
av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
|
||||
goto error;
|
||||
}
|
||||
track->height = track->tag>>24 == 'n' ? 486 : 576;
|
||||
}
|
||||
track->timescale = st->codec->time_base.den;
|
||||
if (track->mode == MODE_MOV && track->timescale > 100000)
|
||||
av_log(s, AV_LOG_WARNING,
|
||||
"WARNING codec timebase is very high. If duration is too long,\n"
|
||||
"file may not be playable by quicktime. Specify a shorter timebase\n"
|
||||
"or choose different container.\n");
|
||||
}else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
|
||||
track->timescale = st->codec->sample_rate;
|
||||
if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: codec frame size is not set\n", i);
|
||||
goto error;
|
||||
}else if(st->codec->frame_size > 1){ /* assume compressed audio */
|
||||
track->audio_vbr = 1;
|
||||
}else{
|
||||
st->codec->frame_size = 1;
|
||||
track->sampleSize = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
|
||||
}
|
||||
if (track->mode != MODE_MOV) {
|
||||
if (track->timescale > UINT16_MAX) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: output format does not support "
|
||||
"sample rate %dhz\n", i, track->timescale);
|
||||
goto error;
|
||||
}
|
||||
if (track->enc->codec_id == CODEC_ID_MP3 && track->timescale < 16000) {
|
||||
av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n",
|
||||
i, track->enc->sample_rate);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}else if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE){
|
||||
track->timescale = st->codec->time_base.den;
|
||||
}
|
||||
if (!track->height)
|
||||
track->height = st->codec->height;
|
||||
|
||||
av_set_pts_info(st, 64, 1, track->timescale);
|
||||
}
|
||||
|
||||
mov_write_mdat_tag(pb, mov);
|
||||
mov->time = s->timestamp + 0x7C25B080; //1970 based -> 1904 based
|
||||
|
||||
if (mov->chapter_track)
|
||||
mov_create_chapter_track(s, mov->chapter_track);
|
||||
|
||||
put_flush_packet(pb);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
av_freep(&mov->tracks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mov_write_trailer(AVFormatContext *s)
|
||||
{
|
||||
MOVMuxContext *mov = s->priv_data;
|
||||
@ -2115,9 +2053,6 @@ static int mov_write_trailer(AVFormatContext *s)
|
||||
|
||||
mov_write_moov_tag(pb, mov, s);
|
||||
|
||||
if (mov->chapter_track)
|
||||
av_freep(&mov->tracks[mov->chapter_track].enc);
|
||||
|
||||
for (i=0; i<mov->nb_streams; i++) {
|
||||
av_freep(&mov->tracks[i].cluster);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user