Mercurial > libavformat.hg
view raw.c @ 2761:5e808c3a55a8 libavformat
When new streams are detected, look for old filters and close them out.
This avoids crashes seen when legitimate streams are found on PID 0x11 instead
of DVB SDT.
Fixes regression detailed in Roundup issue 138.
author | heydowns |
---|---|
date | Sat, 17 Nov 2007 03:14:43 +0000 |
parents | 213268d7594e |
children | d52c718e83f9 |
line wrap: on
line source
/* * RAW muxer and demuxer * Copyright (c) 2001 Fabrice Bellard. * Copyright (c) 2005 Alex Beregszaszi * * 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.1 of the License, or (at your option) any later version. * * 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" #include "ac3_parser.h" #include "raw.h" #ifdef CONFIG_MUXERS /* simple formats */ 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 roq_write_header(struct AVFormatContext *s) { static const uint8_t header[] = { 0x84, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x00 }; put_buffer(&s->pb, header, 8); put_flush_packet(&s->pb); return 0; } static int raw_write_packet(struct AVFormatContext *s, AVPacket *pkt) { put_buffer(&s->pb, pkt->data, pkt->size); put_flush_packet(&s->pb); return 0; } #endif //CONFIG_MUXERS /* raw input */ static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVStream *st; int id; st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); id = s->iformat->value; if (id == CODEC_ID_RAWVIDEO) { st->codec->codec_type = CODEC_TYPE_VIDEO; } else { st->codec->codec_type = CODEC_TYPE_AUDIO; } st->codec->codec_id = id; switch(st->codec->codec_type) { case CODEC_TYPE_AUDIO: st->codec->sample_rate = ap->sample_rate; st->codec->channels = ap->channels; av_set_pts_info(st, 64, 1, st->codec->sample_rate); break; case CODEC_TYPE_VIDEO: av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den); 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; break; default: return -1; } return 0; } #define RAW_PACKET_SIZE 1024 static int raw_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, size; // AVStream *st = s->streams[0]; size= RAW_PACKET_SIZE; ret= av_get_packet(&s->pb, pkt, size); pkt->stream_index = 0; if (ret <= 0) { return AVERROR(EIO); } /* note: we need to modify the packet size here to handle the last packet */ pkt->size = ret; return ret; } static int raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt) { int ret, size; size = RAW_PACKET_SIZE; if (av_new_packet(pkt, size) < 0) return AVERROR(EIO); pkt->pos= url_ftell(&s->pb); pkt->stream_index = 0; ret = get_partial_buffer(&s->pb, pkt->data, size); if (ret <= 0) { av_free_packet(pkt); return AVERROR(EIO); } pkt->size = ret; return ret; } // http://www.artificis.hu/files/texts/ingenient.txt static int ingenient_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, size, w, h, unk1, unk2; if (get_le32(&s->pb) != MKTAG('M', 'J', 'P', 'G')) return AVERROR(EIO); // FIXME size = get_le32(&s->pb); w = get_le16(&s->pb); h = get_le16(&s->pb); 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 av_log(NULL, AV_LOG_DEBUG, "Ingenient packet: size=%d, width=%d, height=%d, unk1=%d unk2=%d\n", size, w, h, unk1, unk2); if (av_new_packet(pkt, size) < 0) return AVERROR(EIO); 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(EIO); } pkt->size = ret; return ret; } static int raw_read_close(AVFormatContext *s) { return 0; } 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; /* recompute exact position */ 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(ENOMEM); st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_AC3; st->need_parsing = AVSTREAM_PARSE_FULL; /* 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(ENOMEM); st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_SHORTEN; st->need_parsing = AVSTREAM_PARSE_FULL; /* the parameters will be extracted from the compressed bitstream */ return 0; } /* flac read */ static int flac_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVStream *st; st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_FLAC; st->need_parsing = AVSTREAM_PARSE_FULL; /* 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(ENOMEM); st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_DTS; st->need_parsing = AVSTREAM_PARSE_FULL; /* 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(ENOMEM); st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_id = CODEC_ID_AAC; st->need_parsing = AVSTREAM_PARSE_FULL; /* 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; st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_id = s->iformat->value; st->need_parsing = AVSTREAM_PARSE_FULL; /* for mjpeg, specify frame rate */ /* for mpeg4 specify it too (most mpeg4 streams do not have the fixed_vop_rate set ...)*/ if (ap->time_base.num) { av_set_pts_info(st, 64, ap->time_base.num, ap->time_base.den); } else if ( st->codec->codec_id == CODEC_ID_MJPEG || st->codec->codec_id == CODEC_ID_MPEG4 || st->codec->codec_id == CODEC_ID_H264) { av_set_pts_info(st, 64, 1, 25); } return 0; } #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) { uint32_t code= -1; 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 return 0; } #define VISUAL_OBJECT_START_CODE 0x000001b5 #define VOP_START_CODE 0x000001b6 static int mpeg4video_probe(AVProbeData *probe_packet) { uint32_t temp_buffer= -1; 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) continue; if (temp_buffer == VOP_START_CODE) VOP++; else if (temp_buffer == VISUAL_OBJECT_START_CODE) VISO++; else if (temp_buffer < 0x120) VO++; else if (temp_buffer < 0x130) VOL++; else if ( !(0x1AF < temp_buffer && temp_buffer < 0x1B7) && !(0x1B9 < temp_buffer && temp_buffer < 0x1C4)) res++; } 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; } 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 = 0, frames; uint8_t *buf, *buf2, *end; AC3HeaderInfo hdr; max_frames = 0; buf = p->buf; end = buf + p->buf_size; 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; } static int flac_probe(AVProbeData *p) { if(memcmp(p->buf, "fLaC", 4)) return 0; else return AVPROBE_SCORE_MAX / 2; } AVInputFormat shorten_demuxer = { "shn", "raw shorten", 0, NULL, shorten_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .extensions = "shn", }; AVInputFormat flac_demuxer = { "flac", "raw flac", 0, flac_probe, flac_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .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, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS #ifdef CONFIG_AC3_DEMUXER AVInputFormat ac3_demuxer = { "ac3", "raw ac3", 0, ac3_probe, ac3_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .extensions = "ac3", }; #endif #ifdef CONFIG_MUXERS AVOutputFormat ac3_muxer = { "ac3", "raw ac3", "audio/x-ac3", "ac3", 0, CODEC_ID_AC3, 0, NULL, raw_write_packet, .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, .extensions = "aac", }; #ifdef CONFIG_ROQ_MUXER AVOutputFormat roq_muxer = { "RoQ", "Id RoQ format", NULL, "roq", 0, CODEC_ID_ROQ_DPCM, CODEC_ID_ROQ, roq_write_header, raw_write_packet, }; #endif //CONFIG_ROQ_MUXER AVInputFormat h261_demuxer = { "h261", "raw h261", 0, h261_probe, video_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .extensions = "h261", .value = CODEC_ID_H261, }; #ifdef CONFIG_MUXERS AVOutputFormat h261_muxer = { "h261", "raw h261", "video/x-h261", "h261", 0, 0, CODEC_ID_H261, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS AVInputFormat h263_demuxer = { "h263", "raw h263", 0, h263_probe, video_read_header, 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, 0, CODEC_ID_H263, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS AVInputFormat m4v_demuxer = { "m4v", "raw MPEG4 video format", 0, mpeg4video_probe, /** probing for mpeg4 data */ video_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .extensions = "m4v", //FIXME remove after writing mpeg4_probe .value = CODEC_ID_MPEG4, }; #ifdef CONFIG_MUXERS AVOutputFormat m4v_muxer = { "m4v", "raw MPEG4 video format", NULL, "m4v", 0, CODEC_ID_NONE, CODEC_ID_MPEG4, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS AVInputFormat h264_demuxer = { "h264", "raw H264 video format", 0, NULL /*mpegvideo_probe*/, video_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .extensions = "h26l,h264,264", //FIXME remove after writing mpeg4_probe .value = CODEC_ID_H264, }; #ifdef CONFIG_MUXERS AVOutputFormat h264_muxer = { "h264", "raw H264 video format", NULL, "h264", 0, CODEC_ID_NONE, CODEC_ID_H264, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS AVInputFormat mpegvideo_demuxer = { "mpegvideo", "MPEG video", 0, mpegvideo_probe, video_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .value = CODEC_ID_MPEG1VIDEO, }; #ifdef CONFIG_MUXERS AVOutputFormat mpeg1video_muxer = { "mpeg1video", "MPEG video", "video/x-mpeg", "mpg,mpeg,m1v", 0, 0, CODEC_ID_MPEG1VIDEO, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS #ifdef CONFIG_MUXERS AVOutputFormat mpeg2video_muxer = { "mpeg2video", "MPEG2 video", NULL, "m2v", 0, 0, CODEC_ID_MPEG2VIDEO, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS AVInputFormat mjpeg_demuxer = { "mjpeg", "MJPEG video", 0, NULL, video_read_header, raw_read_partial_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .extensions = "mjpg,mjpeg", .value = CODEC_ID_MJPEG, }; AVInputFormat ingenient_demuxer = { "ingenient", "Ingenient MJPEG", 0, NULL, video_read_header, ingenient_read_packet, raw_read_close, .flags= AVFMT_GENERIC_INDEX, .extensions = "cgi", // FIXME .value = CODEC_ID_MJPEG, }; #ifdef CONFIG_MUXERS AVOutputFormat mjpeg_muxer = { "mjpeg", "MJPEG video", "video/x-mjpeg", "mjpg,mjpeg", 0, 0, CODEC_ID_MJPEG, NULL, raw_write_packet, .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, }; /* pcm formats */ #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,\ pcm_read_seek,\ .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,\ NULL,\ raw_write_packet,\ .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 #ifdef WORDS_BIGENDIAN #define BE_DEF(s) s #define LE_DEF(s) NULL #else #define BE_DEF(s) NULL #define LE_DEF(s) s #endif PCMDEF(s16le, "pcm signed 16 bit little endian format", LE_DEF("sw"), CODEC_ID_PCM_S16LE) PCMDEF(s16be, "pcm signed 16 bit big endian format", BE_DEF("sw"), CODEC_ID_PCM_S16BE) PCMDEF(u16le, "pcm unsigned 16 bit little endian format", LE_DEF("uw"), CODEC_ID_PCM_U16LE) PCMDEF(u16be, "pcm unsigned 16 bit big endian format", BE_DEF("uw"), CODEC_ID_PCM_U16BE) PCMDEF(s8, "pcm signed 8 bit format", "sb", CODEC_ID_PCM_S8) PCMDEF(u8, "pcm unsigned 8 bit format", "ub", CODEC_ID_PCM_U8) PCMDEF(mulaw, "pcm mu law format", "ul", CODEC_ID_PCM_MULAW) PCMDEF(alaw, "pcm A law format", "al", CODEC_ID_PCM_ALAW) static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt) { int packet_size, ret, width, height; AVStream *st = s->streams[0]; width = st->codec->width; height = st->codec->height; packet_size = avpicture_get_size(st->codec->pix_fmt, width, height); if (packet_size < 0) return -1; ret= av_get_packet(&s->pb, pkt, packet_size); pkt->stream_index = 0; if (ret != packet_size) { return AVERROR(EIO); } else { return 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,rgb", .value = CODEC_ID_RAWVIDEO, }; #ifdef CONFIG_MUXERS AVOutputFormat rawvideo_muxer = { "rawvideo", "raw video format", NULL, "yuv,rgb", 0, CODEC_ID_NONE, CODEC_ID_RAWVIDEO, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS #ifdef CONFIG_MUXERS static int null_write_packet(struct AVFormatContext *s, AVPacket *pkt) { return 0; } 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, NULL, null_write_packet, .flags = AVFMT_NOFILE | AVFMT_RAWPICTURE | AVFMT_NOTIMESTAMPS, }; #endif //CONFIG_MUXERS