/*
- * FFM (ffserver live feed) encoder and decoder
+ * FFM (ffserver live feed) muxer and demuxer
* Copyright (c) 2001 Fabrice Bellard.
*
- * This library is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avformat.h"
{
FFMContext *ffm = s->priv_data;
int fill_size, h;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
fill_size = ffm->packet_end - ffm->packet_ptr;
memset(ffm->packet_ptr, 0, fill_size);
FFMContext *ffm = s->priv_data;
AVStream *st;
FFMStream *fst;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *codec;
int bit_rate, i;
put_be32(pb, codec->nsse_weight);
put_be32(pb, codec->frame_skip_cmp);
put_be64(pb, av_dbl2int(codec->rc_buffer_aggressivity));
+ put_be32(pb, codec->codec_tag);
break;
case CODEC_TYPE_AUDIO:
put_be32(pb, codec->sample_rate);
FFMStream *fst = st->priv_data;
int64_t pts;
uint8_t header[FRAME_HEADER_SIZE];
- int duration;
- int size= pkt->size;
-
- //XXX/FIXME use duration from pkt
- if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
- duration = ((float)st->codec->frame_size / st->codec->sample_rate * 1000000.0);
- } else {
- duration = (1000000.0 * st->codec->time_base.num / (float)st->codec->time_base.den);
- }
pts = fst->pts;
/* packet size & key_frame */
header[1] = 0;
if (pkt->flags & PKT_FLAG_KEY)
header[1] |= FLAG_KEY_FRAME;
- header[2] = (size >> 16) & 0xff;
- header[3] = (size >> 8) & 0xff;
- header[4] = size & 0xff;
- header[5] = (duration >> 16) & 0xff;
- header[6] = (duration >> 8) & 0xff;
- header[7] = duration & 0xff;
+ AV_WB24(header+2, pkt->size);
+ AV_WB24(header+5, pkt->duration);
ffm_write_data(s, header, FRAME_HEADER_SIZE, pts, 1);
- ffm_write_data(s, pkt->data, size, pts, 0);
+ ffm_write_data(s, pkt->data, pkt->size, pts, 0);
- fst->pts += duration;
+ fst->pts += pkt->duration;
return 0;
}
static int ffm_write_trailer(AVFormatContext *s)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
FFMContext *ffm = s->priv_data;
/* flush packets */
if (size <= len)
return 1;
}
- pos = url_ftell(&s->pb);
+ pos = url_ftell(s->pb);
if (pos == ffm->write_index) {
/* exactly at the end of stream */
return 0;
uint8_t *buf, int size, int first)
{
FFMContext *ffm = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int len, fill_size, size1, frame_offset;
size1 = size;
static void adjust_write_index(AVFormatContext *s)
{
FFMContext *ffm = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int64_t pts;
//offset_t orig_write_index = ffm->write_index;
offset_t pos_min, pos_max;
ffm->write_index += pos_max;
}
- //printf("Adjusted write index from %lld to %lld: pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.);
+ //printf("Adjusted write index from %"PRId64" to %"PRId64": pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.);
//printf("pts range %0.6f - %0.6f\n", get_pts(s, 0) / 1000000. , get_pts(s, ffm->file_size - 2 * FFM_PACKET_SIZE) / 1000000. );
end:
FFMContext *ffm = s->priv_data;
AVStream *st;
FFMStream *fst;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVCodecContext *codec;
int i, nb_streams;
uint32_t tag;
ffm->file_size = url_fsize(pb);
adjust_write_index(s);
} else {
- ffm->file_size = (uint64_t_C(1) << 63) - 1;
+ ffm->file_size = (UINT64_C(1) << 63) - 1;
}
nb_streams = get_be32(pb);
codec->nsse_weight = get_be32(pb);
codec->frame_skip_cmp = get_be32(pb);
codec->rc_buffer_aggressivity = av_int2dbl(get_be64(pb));
+ codec->codec_tag = get_be32(pb);
break;
case CODEC_TYPE_AUDIO:
codec->sample_rate = get_be32(pb);
switch(ffm->read_state) {
case READ_HEADER:
if (!ffm_is_avail_data(s, FRAME_HEADER_SIZE)) {
- return -EAGAIN;
+ return AVERROR(EAGAIN);
}
#if 0
- printf("pos=%08Lx spos=%Lx, write_index=%Lx size=%Lx\n",
- url_ftell(&s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
+ printf("pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n",
+ url_ftell(s->pb), s->pb.pos, ffm->write_index, ffm->file_size);
#endif
if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) !=
FRAME_HEADER_SIZE)
- return -EAGAIN;
+ return AVERROR(EAGAIN);
#if 0
{
int i;
ffm->read_state = READ_DATA;
/* fall thru */
case READ_DATA:
- size = (ffm->header[2] << 16) | (ffm->header[3] << 8) | ffm->header[4];
+ size = AV_RB24(ffm->header + 2);
if (!ffm_is_avail_data(s, size)) {
- return -EAGAIN;
+ return AVERROR(EAGAIN);
}
- duration = (ffm->header[5] << 16) | (ffm->header[6] << 8) | ffm->header[7];
+ duration = AV_RB24(ffm->header + 5);
av_new_packet(pkt, size);
pkt->stream_index = ffm->header[0];
- pkt->pos = url_ftell(&s->pb);
+ if ((unsigned)pkt->stream_index >= s->nb_streams) {
+ av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index);
+ av_free_packet(pkt);
+ ffm->read_state = READ_HEADER;
+ return AVERROR(EAGAIN);
+ }
+ pkt->pos = url_ftell(s->pb);
if (ffm->header[1] & FLAG_KEY_FRAME)
pkt->flags |= PKT_FLAG_KEY;
if (ffm_read_data(s, pkt->data, size, 0) != size) {
/* bad case: desynchronized packet. we cancel all the packet loading */
av_free_packet(pkt);
- return -EAGAIN;
+ return AVERROR(EAGAIN);
}
if (ffm->first_frame_in_packet)
{
static void ffm_seek1(AVFormatContext *s, offset_t pos1)
{
FFMContext *ffm = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
offset_t pos;
pos = pos1 + ffm->write_index;
if (pos >= ffm->file_size)
pos -= (ffm->file_size - FFM_PACKET_SIZE);
#ifdef DEBUG_SEEK
- printf("seek to %Lx -> %Lx\n", pos1, pos);
+ printf("seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos);
#endif
url_fseek(pb, pos, SEEK_SET);
}
static int64_t get_pts(AVFormatContext *s, offset_t pos)
{
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int64_t pts;
ffm_seek1(s, pos);
}
/* seek to a given time in the file. The file read pointer is
- positionned at or before pts. XXX: the following code is quite
+ positioned at or before pts. XXX: the following code is quite
approximative */
static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)
{
return 0;
}
+#ifdef CONFIG_FFSERVER
offset_t ffm_read_write_index(int fd)
{
uint8_t buf[8];
- offset_t pos;
- int i;
lseek(fd, 8, SEEK_SET);
read(fd, buf, 8);
- pos = 0;
- for(i=0;i<8;i++)
- pos |= (int64_t)buf[i] << (56 - i * 8);
- return pos;
+ return AV_RB64(buf);
}
void ffm_write_write_index(int fd, offset_t pos)
ffm->write_index = pos;
ffm->file_size = file_size;
}
+#endif // CONFIG_FFSERVER
static int ffm_read_close(AVFormatContext *s)
{
static int ffm_probe(AVProbeData *p)
{
- if (p->buf_size >= 4 &&
+ if (
p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&
p->buf[3] == '1')
return AVPROBE_SCORE_MAX + 1;
return 0;
}
-static AVInputFormat ffm_iformat = {
+#ifdef CONFIG_FFM_DEMUXER
+AVInputFormat ffm_demuxer = {
"ffm",
"ffm format",
sizeof(FFMContext),
ffm_read_close,
ffm_seek,
};
-
-#ifdef CONFIG_MUXERS
-static AVOutputFormat ffm_oformat = {
+#endif
+#ifdef CONFIG_FFM_MUXER
+AVOutputFormat ffm_muxer = {
"ffm",
"ffm format",
"",
ffm_write_packet,
ffm_write_trailer,
};
-#endif //CONFIG_MUXERS
-
-int ffm_init(void)
-{
- av_register_input_format(&ffm_iformat);
-#ifdef CONFIG_MUXERS
- av_register_output_format(&ffm_oformat);
-#endif //CONFIG_MUXERS
- return 0;
-}
+#endif //CONFIG_FFM_MUXER