00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "libavutil/intreadwrite.h"
00028 #include "libavutil/avstring.h"
00029 #include "avformat.h"
00030 #include "sauce.h"
00031 #include <strings.h>
00032
00033 #define LINE_RATE 6000
00034
00035 typedef struct {
00036 int chars_per_frame;
00037 uint64_t fsize;
00038 } TtyDemuxContext;
00039
00043 static int efi_read(AVFormatContext *avctx, uint64_t start_pos)
00044 {
00045 TtyDemuxContext *s = avctx->priv_data;
00046 ByteIOContext *pb = avctx->pb;
00047 char buf[37];
00048 int len;
00049
00050 url_fseek(pb, start_pos, SEEK_SET);
00051 if (get_byte(pb) != 0x1A)
00052 return -1;
00053
00054 #define GET_EFI_META(name,size) \
00055 len = get_byte(pb); \
00056 if (len < 1 || len > size) \
00057 return -1; \
00058 if (get_buffer(pb, buf, size) == size) { \
00059 buf[len] = 0; \
00060 av_metadata_set2(&avctx->metadata, name, buf, 0); \
00061 }
00062
00063 GET_EFI_META("filename", 12)
00064 GET_EFI_META("title", 36)
00065
00066 s->fsize = start_pos;
00067 return 0;
00068 }
00069
00070 static int read_header(AVFormatContext *avctx,
00071 AVFormatParameters *ap)
00072 {
00073 TtyDemuxContext *s = avctx->priv_data;
00074 AVStream *st = av_new_stream(avctx, 0);
00075 if (!st)
00076 return AVERROR(ENOMEM);
00077 st->codec->codec_tag = 0;
00078 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00079 st->codec->codec_id = CODEC_ID_ANSI;
00080 if (ap->width) st->codec->width = ap->width;
00081 if (ap->height) st->codec->height = ap->height;
00082
00083 if (!ap->time_base.num) {
00084 av_set_pts_info(st, 60, 1, 25);
00085 } else {
00086 av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den);
00087 }
00088
00089
00090 s->chars_per_frame = FFMAX(av_q2d(st->time_base) * (ap->sample_rate ? ap->sample_rate : LINE_RATE), 1);
00091
00092 if (!url_is_streamed(avctx->pb)) {
00093 s->fsize = url_fsize(avctx->pb);
00094 st->duration = (s->fsize + s->chars_per_frame - 1) / s->chars_per_frame;
00095
00096 if (ff_sauce_read(avctx, &s->fsize, 0, 0) < 0)
00097 efi_read(avctx, s->fsize - 51);
00098
00099 url_fseek(avctx->pb, 0, SEEK_SET);
00100 }
00101
00102 return 0;
00103 }
00104
00105 static int read_packet(AVFormatContext *avctx, AVPacket *pkt)
00106 {
00107 TtyDemuxContext *s = avctx->priv_data;
00108 int n;
00109
00110 if (url_feof(avctx->pb))
00111 return AVERROR_EOF;
00112
00113 n = s->chars_per_frame;
00114 if (s->fsize) {
00115
00116 uint64_t p = url_ftell(avctx->pb);
00117 if (p + s->chars_per_frame > s->fsize)
00118 n = s->fsize - p;
00119 }
00120
00121 pkt->size = av_get_packet(avctx->pb, pkt, n);
00122 if (pkt->size <= 0)
00123 return AVERROR(EIO);
00124 pkt->flags |= PKT_FLAG_KEY;
00125 return 0;
00126 }
00127
00128 AVInputFormat tty_demuxer = {
00129 .name = "tty",
00130 .long_name = NULL_IF_CONFIG_SMALL("Tele-typewriter"),
00131 .priv_data_size = sizeof(TtyDemuxContext),
00132 .read_header = read_header,
00133 .read_packet = read_packet,
00134 .extensions = "ans,art,asc,diz,ice,nfo,txt,vt",
00135 };