Newer
Older
* RAW muxer and demuxer
Alex Beregszaszi
committed
* Copyright (c) 2005 Alex Beregszaszi
Diego Biurrun
committed
* 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
Diego Biurrun
committed
* version 2.1 of the License, or (at your option) any later version.
Diego Biurrun
committed
* 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
Diego Biurrun
committed
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Diego Biurrun
committed
#include "parser.h"
#ifdef CONFIG_MUXERS
static int raw_write_header(struct AVFormatContext *s)
static int flac_write_header(struct AVFormatContext *s)
{
static const uint8_t header[8] = {
0x66, 0x4C, 0x61, 0x43, 0x80, 0x00, 0x00, 0x22
};
uint8_t *streaminfo = s->streams[0]->codec->extradata;
int len = s->streams[0]->codec->extradata_size;
if(streaminfo != NULL && len > 0) {
put_buffer(&s->pb, header, 8);
put_buffer(&s->pb, streaminfo, len);
}
return 0;
}
static int raw_write_packet(struct AVFormatContext *s, AVPacket *pkt)
put_buffer(&s->pb, pkt->data, pkt->size);
static int raw_write_trailer(struct AVFormatContext *s)
#endif //CONFIG_MUXERS
static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap)
id = s->iformat->value;
if (id == CODEC_ID_RAWVIDEO) {
Michael Niedermayer
committed
st->codec->codec_type = CODEC_TYPE_VIDEO;
Michael Niedermayer
committed
st->codec->codec_type = CODEC_TYPE_AUDIO;
Michael Niedermayer
committed
st->codec->codec_id = id;
Michael Niedermayer
committed
switch(st->codec->codec_type) {
Michael Niedermayer
committed
st->codec->sample_rate = ap->sample_rate;
st->codec->channels = ap->channels;
av_set_pts_info(st, 64, 1, st->codec->sample_rate);
av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den);
Michael Niedermayer
committed
st->codec->width = ap->width;
st->codec->height = ap->height;
st->codec->pix_fmt = ap->pix_fmt;
if(st->codec->pix_fmt == PIX_FMT_NONE)
st->codec->pix_fmt= PIX_FMT_YUV420P;
static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
size= RAW_PACKET_SIZE;
}
/* note: we need to modify the packet size here to handle the last
packet */
pkt->size = ret;
Leon van Stuivenberg
committed
static int raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, size;
size = RAW_PACKET_SIZE;
if (av_new_packet(pkt, size) < 0)
Leon van Stuivenberg
committed
pkt->stream_index = 0;
ret = get_partial_buffer(&s->pb, pkt->data, size);
if (ret <= 0) {
av_free_packet(pkt);
Leon van Stuivenberg
committed
}
pkt->size = ret;
return ret;
}
Alex Beregszaszi
committed
// http://www.artificis.hu/files/texts/ingenient.txt
static int ingenient_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int ret, size, w, h, unk1, unk2;
Alex Beregszaszi
committed
if (get_le32(&s->pb) != MKTAG('M', 'J', 'P', 'G'))
return AVERROR_IO; // FIXME
Alex Beregszaszi
committed
size = get_le32(&s->pb);
Alex Beregszaszi
committed
w = get_le16(&s->pb);
h = get_le16(&s->pb);
Alex Beregszaszi
committed
url_fskip(&s->pb, 8); // zero + size (padded?)
url_fskip(&s->pb, 2);
unk1 = get_le16(&s->pb);
unk2 = get_le16(&s->pb);
url_fskip(&s->pb, 22); // ascii timestamp
Alex Beregszaszi
committed
av_log(NULL, AV_LOG_DEBUG, "Ingenient packet: size=%d, width=%d, height=%d, unk1=%d unk2=%d\n",
size, w, h, unk1, unk2);
Alex Beregszaszi
committed
if (av_new_packet(pkt, size) < 0)
return AVERROR_IO;
pkt->pos = url_ftell(&s->pb);
pkt->stream_index = 0;
ret = get_buffer(&s->pb, pkt->data, size);
if (ret <= 0) {
av_free_packet(pkt);
return AVERROR_IO;
}
pkt->size = ret;
return ret;
}
static int raw_read_close(AVFormatContext *s)
int pcm_read_seek(AVFormatContext *s,
int stream_index, int64_t timestamp, int flags)
{
AVStream *st;
int block_align, byte_rate;
int64_t pos;
st = s->streams[0];
block_align = st->codec->block_align ? st->codec->block_align :
(av_get_bits_per_sample(st->codec->codec_id) * st->codec->channels) >> 3;
byte_rate = st->codec->bit_rate ? st->codec->bit_rate >> 3 :
block_align * st->codec->sample_rate;
if (block_align <= 0 || byte_rate <= 0)
return -1;
/* compute the position by aligning it to block_align */
pos = av_rescale_rnd(timestamp * byte_rate,
st->time_base.num,
st->time_base.den * (int64_t)block_align,
(flags & AVSEEK_FLAG_BACKWARD) ? AV_ROUND_DOWN : AV_ROUND_UP);
pos *= block_align;
st->cur_dts = av_rescale(pos, st->time_base.den, byte_rate * (int64_t)st->time_base.num);
url_fseek(&s->pb, pos + s->data_offset, SEEK_SET);
return 0;
}
/* ac3 read */
static int ac3_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
st = av_new_stream(s, 0);
if (!st)
return AVERROR_NOMEM;
Michael Niedermayer
committed
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_AC3;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
static int shorten_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
st = av_new_stream(s, 0);
if (!st)
return AVERROR_NOMEM;
Michael Niedermayer
committed
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_SHORTEN;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
Benjamin Larsson
committed
/* flac read */
static int flac_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
st = av_new_stream(s, 0);
if (!st)
return AVERROR_NOMEM;
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_FLAC;
Benjamin Larsson
committed
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
/* dts read */
static int dts_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
st = av_new_stream(s, 0);
if (!st)
return AVERROR_NOMEM;
Michael Niedermayer
committed
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_DTS;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
/* aac read */
static int aac_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
st = av_new_stream(s, 0);
if (!st)
return AVERROR_NOMEM;
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->codec_id = CODEC_ID_AAC;
/* the parameters will be extracted from the compressed bitstream */
return 0;
}
/* mpeg1/h263 input */
static int video_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
Michael Niedermayer
committed
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->codec_id = s->iformat->value;
/* for mpeg4 specify it too (most mpeg4 streams dont have the fixed_vop_rate set ...)*/
av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den);
} else if ( st->codec->codec_id == CODEC_ID_MJPEG ||
Michael Niedermayer
committed
st->codec->codec_id == CODEC_ID_MPEG4 ||
st->codec->codec_id == CODEC_ID_H264) {
av_set_pts_info(st, 64, 1, 25);
#define SEQ_START_CODE 0x000001b3
#define GOP_START_CODE 0x000001b8
#define PICTURE_START_CODE 0x00000100
#define SLICE_START_CODE 0x00000101
#define PACK_START_CODE 0x000001ba
#define VIDEO_ID 0x000001e0
#define AUDIO_ID 0x000001c0
static int mpegvideo_probe(AVProbeData *p)
{
int pic=0, seq=0, slice=0, pspack=0, pes=0;
int i;
for(i=0; i<p->buf_size; i++){
code = (code<<8) + p->buf[i];
if ((code & 0xffffff00) == 0x100) {
switch(code){
case SEQ_START_CODE: seq++; break;
case PICTURE_START_CODE: pic++; break;
case SLICE_START_CODE: slice++; break;
case PACK_START_CODE: pspack++; break;
}
if ((code & 0x1f0) == VIDEO_ID) pes++;
else if((code & 0x1e0) == AUDIO_ID) pes++;
if(seq && seq*9<=pic*10 && pic*9<=slice*10 && !pspack && !pes)
return AVPROBE_SCORE_MAX/2+1; // +1 for .mpg
#define VISUAL_OBJECT_START_CODE 0x000001b5
#define VOP_START_CODE 0x000001b6
static int mpeg4video_probe(AVProbeData *probe_packet)
{
uint32_t temp_buffer= -1;
Michael Niedermayer
committed
int VO=0, VOL=0, VOP = 0, VISO = 0, res=0;
int i;
for(i=0; i<probe_packet->buf_size; i++){
temp_buffer = (temp_buffer<<8) + probe_packet->buf[i];
if ((temp_buffer & 0xffffff00) == 0x100) {
switch(temp_buffer){
case VOP_START_CODE: VOP++; break;
case VISUAL_OBJECT_START_CODE: VISO++; break;
Michael Niedermayer
committed
case 0x100 ... 0x11F: VO++; break;
case 0x120 ... 0x12F: VOL++; break;
case 0x130 ... 0x1AF:
case 0x1B7 ... 0x1B9:
case 0x1C4 ... 0x1FF: res++; break;
}
}
}
Michael Niedermayer
committed
if ( VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0 && res==0)
return AVPROBE_SCORE_MAX/2;
return 0;
}
static int h263_probe(AVProbeData *p)
{
int code;
const uint8_t *d;
d = p->buf;
code = (d[0] << 14) | (d[1] << 6) | (d[2] >> 2);
if (code == 0x20) {
return 50;
}
return 0;
}
Michael Niedermayer
committed
static int h261_probe(AVProbeData *p)
{
int code;
const uint8_t *d;
d = p->buf;
code = (d[0] << 12) | (d[1] << 4) | (d[2] >> 4);
if (code == 0x10) {
return 50;
}
return 0;
}
static int ac3_probe(AVProbeData *p)
{
int max_frames, first_frames, frames;
uint8_t *buf, *buf2, *end;
AC3HeaderInfo hdr;
max_frames = 0;
buf = p->buf;
end = buf + FFMIN(4096, p->buf_size - 7);
for(; buf < end; buf++) {
buf2 = buf;
for(frames = 0; buf2 < end; frames++) {
if(ff_ac3_parse_header(buf2, &hdr) < 0)
break;
buf2 += hdr.frame_size;
}
max_frames = FFMAX(max_frames, frames);
if(buf == p->buf)
first_frames = frames;
}
if (first_frames>=3) return AVPROBE_SCORE_MAX * 3 / 4;
else if(max_frames>=3) return AVPROBE_SCORE_MAX / 2;
else if(max_frames>=1) return 1;
else return 0;
AVInputFormat shorten_demuxer = {
Alex Beregszaszi
committed
"raw shorten",
0,
NULL,
shorten_read_header,
raw_read_partial_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
.extensions = "shn",
};
AVInputFormat flac_demuxer = {
Benjamin Larsson
committed
"flac",
"raw flac",
0,
NULL,
flac_read_header,
raw_read_partial_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
Benjamin Larsson
committed
.extensions = "flac",
};
#ifdef CONFIG_MUXERS
AVOutputFormat flac_muxer = {
"flac",
"raw flac",
"audio/x-flac",
"flac",
0,
CODEC_ID_FLAC,
0,
flac_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
};
#endif //CONFIG_MUXERS
#ifdef CONFIG_AC3_DEMUXER
AVInputFormat ac3_demuxer = {
Leon van Stuivenberg
committed
raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
Måns Rullgård
committed
.extensions = "ac3",
#ifdef CONFIG_MUXERS
AVOutputFormat ac3_muxer = {
CODEC_ID_AC3,
0,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
#endif //CONFIG_MUXERS
AVInputFormat dts_demuxer = {
"dts",
"raw dts",
0,
NULL,
dts_read_header,
raw_read_partial_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
.extensions = "dts",
};
AVInputFormat aac_demuxer = {
"aac",
"ADTS AAC",
0,
NULL,
aac_read_header,
raw_read_partial_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
AVInputFormat h261_demuxer = {
Michael Niedermayer
committed
"h261",
"raw h261",
0,
h261_probe,
video_read_header,
raw_read_partial_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
Michael Niedermayer
committed
.extensions = "h261",
.value = CODEC_ID_H261,
};
#ifdef CONFIG_MUXERS
AVOutputFormat h261_muxer = {
Michael Niedermayer
committed
"h261",
"raw h261",
"video/x-h261",
"h261",
0,
0,
CODEC_ID_H261,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
Michael Niedermayer
committed
};
#endif //CONFIG_MUXERS
Michael Niedermayer
committed
AVInputFormat h263_demuxer = {
"h263",
"raw h263",
0,
h263_probe,
video_read_header,
Leon van Stuivenberg
committed
raw_read_partial_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
// .extensions = "h263", //FIXME remove after writing mpeg4_probe
.value = CODEC_ID_H263,
};
#ifdef CONFIG_MUXERS
AVOutputFormat h263_muxer = {
"h263",
"raw h263",
"video/x-h263",
"h263",
0,
CODEC_ID_H263,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
#endif //CONFIG_MUXERS
AVInputFormat m4v_demuxer = {
mpeg4video_probe, /** probing for mpeg4 data */
Leon van Stuivenberg
committed
raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
Måns Rullgård
committed
.extensions = "m4v", //FIXME remove after writing mpeg4_probe
.value = CODEC_ID_MPEG4,
#ifdef CONFIG_MUXERS
AVOutputFormat m4v_muxer = {
Max Krasnyansky
committed
"m4v",
"raw MPEG4 video format",
NULL,
"m4v",
0,
CODEC_ID_NONE,
CODEC_ID_MPEG4,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
Max Krasnyansky
committed
};
#endif //CONFIG_MUXERS
Max Krasnyansky
committed
AVInputFormat h264_demuxer = {
"h264",
"raw H264 video format",
0,
NULL /*mpegvideo_probe*/,
video_read_header,
Leon van Stuivenberg
committed
raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
.extensions = "h26l,h264,264", //FIXME remove after writing mpeg4_probe
#ifdef CONFIG_MUXERS
AVOutputFormat h264_muxer = {
"h264",
"raw H264 video format",
NULL,
"h264",
0,
CODEC_ID_NONE,
CODEC_ID_H264,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
#endif //CONFIG_MUXERS
AVInputFormat mpegvideo_demuxer = {
"mpegvideo",
"MPEG video",
0,
mpegvideo_probe,
Leon van Stuivenberg
committed
raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
Måns Rullgård
committed
.value = CODEC_ID_MPEG1VIDEO,
#ifdef CONFIG_MUXERS
AVOutputFormat mpeg1video_muxer = {
CODEC_ID_MPEG1VIDEO,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
#endif //CONFIG_MUXERS
#ifdef CONFIG_MUXERS
AVOutputFormat mpeg2video_muxer = {
Michael Niedermayer
committed
"mpeg2video",
"MPEG2 video",
NULL,
"m2v",
0,
0,
CODEC_ID_MPEG2VIDEO,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
Michael Niedermayer
committed
};
#endif //CONFIG_MUXERS
Michael Niedermayer
committed
AVInputFormat mjpeg_demuxer = {
Leon van Stuivenberg
committed
raw_read_partial_packet,
.flags= AVFMT_GENERIC_INDEX,
Måns Rullgård
committed
.extensions = "mjpg,mjpeg",
.value = CODEC_ID_MJPEG,
AVInputFormat ingenient_demuxer = {
Alex Beregszaszi
committed
"ingenient",
"Ingenient MJPEG",
0,
NULL,
video_read_header,
ingenient_read_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
Alex Beregszaszi
committed
.extensions = "cgi", // FIXME
.value = CODEC_ID_MJPEG,
};
#ifdef CONFIG_MUXERS
AVOutputFormat mjpeg_muxer = {
"mjpeg",
"MJPEG video",
"video/x-mjpeg",
"mjpg,mjpeg",
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
#endif //CONFIG_MUXERS
AVInputFormat vc1_demuxer = {
"vc1",
"raw vc1",
0,
NULL /* vc1_probe */,
video_read_header,
raw_read_partial_packet,
raw_read_close,
.extensions = "vc1",
.value = CODEC_ID_VC1,
};
#define PCMINPUTDEF(name, long_name, ext, codec) \
AVInputFormat pcm_ ## name ## _demuxer = {\
#name,\
long_name,\
0,\
NULL,\
raw_read_header,\
raw_read_packet,\
raw_read_close,\
.flags= AVFMT_GENERIC_INDEX,\
.extensions = ext,\
.value = codec,\
};
#define PCMOUTPUTDEF(name, long_name, ext, codec) \
AVOutputFormat pcm_ ## name ## _muxer = {\
#name,\
long_name,\
NULL,\
ext,\
0,\
codec,\
0,\
raw_write_header,\
raw_write_packet,\
raw_write_trailer,\
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,\
#if !defined(CONFIG_MUXERS) && defined(CONFIG_DEMUXERS)
#define PCMDEF(name, long_name, ext, codec) \
PCMINPUTDEF(name, long_name, ext, codec)
#elif defined(CONFIG_MUXERS) && !defined(CONFIG_DEMUXERS)
#define PCMDEF(name, long_name, ext, codec) \
PCMOUTPUTDEF(name, long_name, ext, codec)
#elif defined(CONFIG_MUXERS) && defined(CONFIG_DEMUXERS)
#define PCMDEF(name, long_name, ext, codec) \
PCMINPUTDEF(name, long_name, ext, codec)\
PCMOUTPUTDEF(name, long_name, ext, codec)
#else
#define PCMDEF(name, long_name, ext, codec)
#endif
PCMDEF(s16le, "pcm signed 16 bit little endian format",
PCMDEF(s16be, "pcm signed 16 bit big endian format",
PCMDEF(u16le, "pcm unsigned 16 bit little endian format",
PCMDEF(u16be, "pcm unsigned 16 bit big endian format",
PCMDEF(s8, "pcm signed 8 bit format",
PCMDEF(u8, "pcm unsigned 8 bit format",
PCMDEF(mulaw, "pcm mu law format",
PCMDEF(alaw, "pcm A law format",
static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt)
{
int packet_size, ret, width, height;
AVStream *st = s->streams[0];
Michael Niedermayer
committed
width = st->codec->width;
height = st->codec->height;
Michael Niedermayer
committed
packet_size = avpicture_get_size(st->codec->pix_fmt, width, height);
if (packet_size < 0)
AVInputFormat rawvideo_demuxer = {
"rawvideo",
"raw video format",
0,
NULL,
raw_read_header,
rawvideo_read_packet,
raw_read_close,
.flags= AVFMT_GENERIC_INDEX,
.extensions = "yuv,cif,qcif",
Måns Rullgård
committed
.value = CODEC_ID_RAWVIDEO,
#ifdef CONFIG_MUXERS
AVOutputFormat rawvideo_muxer = {
CODEC_ID_NONE,
CODEC_ID_RAWVIDEO,
raw_write_header,
raw_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags= AVFMT_NOTIMESTAMPS,
#endif //CONFIG_MUXERS
#ifdef CONFIG_MUXERS
static int null_write_packet(struct AVFormatContext *s, AVPacket *pkt)
AVOutputFormat null_muxer = {
"null",
"null video format",
NULL,
NULL,
0,
#ifdef WORDS_BIGENDIAN
CODEC_ID_PCM_S16BE,
#else
CODEC_ID_PCM_S16LE,
#endif
CODEC_ID_RAWVIDEO,
raw_write_header,
null_write_packet,
raw_write_trailer,
Michael Niedermayer
committed
.flags = AVFMT_NOFILE | AVFMT_RAWPICTURE | AVFMT_NOTIMESTAMPS,
#endif //CONFIG_MUXERS