libavformat/yop.c
Go to the documentation of this file.
1 /*
2  * Psygnosis YOP demuxer
3  *
4  * Copyright (C) 2010 Mohamed Naufal Basheer <naufal11@gmail.com>
5  * derived from the code by
6  * Copyright (C) 2009 Thomas P. Higdon <thomas.p.higdon@gmail.com>
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
26 #include "libavutil/intreadwrite.h"
27 #include "avformat.h"
28 #include "internal.h"
29 
30 typedef struct yop_dec_context {
32 
33  int odd_frame;
38 
39 static int yop_probe(AVProbeData *probe_packet)
40 {
41  if (AV_RB16(probe_packet->buf) == AV_RB16("YO") &&
42  probe_packet->buf[2]<10 &&
43  probe_packet->buf[3]<10 &&
44  probe_packet->buf[6] &&
45  probe_packet->buf[7] &&
46  !(probe_packet->buf[8] & 1) &&
47  !(probe_packet->buf[10] & 1) &&
48  AV_RL16(probe_packet->buf + 12 + 6) >= 920 &&
49  AV_RL16(probe_packet->buf + 12 + 6) < probe_packet->buf[12] * 3 + 4 + probe_packet->buf[7] * 2048
50  )
51  return AVPROBE_SCORE_MAX * 3 / 4;
52 
53  return 0;
54 }
55 
57 {
58  YopDecContext *yop = s->priv_data;
59  AVIOContext *pb = s->pb;
60 
61  AVCodecContext *audio_dec, *video_dec;
63 
64  int frame_rate, ret;
65 
66  audio_stream = avformat_new_stream(s, NULL);
67  video_stream = avformat_new_stream(s, NULL);
68  if (!audio_stream || !video_stream)
69  return AVERROR(ENOMEM);
70 
71  // Extra data that will be passed to the decoder
72  video_stream->codec->extradata_size = 8;
73 
74  video_stream->codec->extradata = av_mallocz(video_stream->codec->extradata_size +
76 
77  if (!video_stream->codec->extradata)
78  return AVERROR(ENOMEM);
79 
80  // Audio
81  audio_dec = audio_stream->codec;
82  audio_dec->codec_type = AVMEDIA_TYPE_AUDIO;
84  audio_dec->channels = 1;
85  audio_dec->channel_layout = AV_CH_LAYOUT_MONO;
86  audio_dec->sample_rate = 22050;
87 
88  // Video
89  video_dec = video_stream->codec;
90  video_dec->codec_type = AVMEDIA_TYPE_VIDEO;
91  video_dec->codec_id = AV_CODEC_ID_YOP;
92 
93  avio_skip(pb, 6);
94 
95  frame_rate = avio_r8(pb);
96  yop->frame_size = avio_r8(pb) * 2048;
97  video_dec->width = avio_rl16(pb);
98  video_dec->height = avio_rl16(pb);
99 
100  video_stream->sample_aspect_ratio = (AVRational){1, 2};
101 
102  ret = avio_read(pb, video_dec->extradata, 8);
103  if (ret < 8)
104  return ret < 0 ? ret : AVERROR_EOF;
105 
106  yop->palette_size = video_dec->extradata[0] * 3 + 4;
107  yop->audio_block_length = AV_RL16(video_dec->extradata + 6);
108 
109  video_dec->bit_rate = 8 * (yop->frame_size - yop->audio_block_length) * frame_rate;
110 
111  // 1840 samples per frame, 1 nibble per sample; hence 1840/2 = 920
112  if (yop->audio_block_length < 920 ||
113  yop->audio_block_length + yop->palette_size >= yop->frame_size) {
114  av_log(s, AV_LOG_ERROR, "YOP has invalid header\n");
115  return AVERROR_INVALIDDATA;
116  }
117 
118  avio_seek(pb, 2048, SEEK_SET);
119 
120  avpriv_set_pts_info(video_stream, 32, 1, frame_rate);
121 
122  return 0;
123 }
124 
126 {
127  YopDecContext *yop = s->priv_data;
128  AVIOContext *pb = s->pb;
129 
130  int ret;
131  int actual_video_data_size = yop->frame_size -
132  yop->audio_block_length - yop->palette_size;
133 
134  yop->video_packet.stream_index = 1;
135 
136  if (yop->video_packet.data) {
137  *pkt = yop->video_packet;
138  memset(&yop->video_packet, 0, sizeof(yop->video_packet));
139  pkt->data[0] = yop->odd_frame;
140  pkt->flags |= AV_PKT_FLAG_KEY;
141  yop->odd_frame ^= 1;
142  return pkt->size;
143  }
144  ret = av_new_packet(&yop->video_packet,
145  yop->frame_size - yop->audio_block_length);
146  if (ret < 0)
147  return ret;
148 
149  yop->video_packet.pos = avio_tell(pb);
150 
151  ret = avio_read(pb, yop->video_packet.data, yop->palette_size);
152  if (ret < 0) {
153  goto err_out;
154  }else if (ret < yop->palette_size) {
155  ret = AVERROR_EOF;
156  goto err_out;
157  }
158 
159  ret = av_get_packet(pb, pkt, 920);
160  if (ret < 0)
161  goto err_out;
162 
163  // Set position to the start of the frame
164  pkt->pos = yop->video_packet.pos;
165 
166  avio_skip(pb, yop->audio_block_length - ret);
167 
168  ret = avio_read(pb, yop->video_packet.data + yop->palette_size,
169  actual_video_data_size);
170  if (ret < 0)
171  goto err_out;
172  else if (ret < actual_video_data_size)
173  av_shrink_packet(&yop->video_packet, yop->palette_size + ret);
174 
175  // Arbitrarily return the audio data first
176  return yop->audio_block_length;
177 
178 err_out:
179  av_free_packet(&yop->video_packet);
180  return ret;
181 }
182 
184 {
185  YopDecContext *yop = s->priv_data;
186  av_free_packet(&yop->video_packet);
187  return 0;
188 }
189 
190 static int yop_read_seek(AVFormatContext *s, int stream_index,
191  int64_t timestamp, int flags)
192 {
193  YopDecContext *yop = s->priv_data;
194  int64_t frame_pos, pos_min, pos_max;
195  int frame_count;
196 
197  if (!stream_index)
198  return -1;
199 
200  pos_min = s->data_offset;
201  pos_max = avio_size(s->pb) - yop->frame_size;
202  frame_count = (pos_max - pos_min) / yop->frame_size;
203 
204  timestamp = FFMAX(0, FFMIN(frame_count, timestamp));
205 
206  frame_pos = timestamp * yop->frame_size + pos_min;
207 
208  if (avio_seek(s->pb, frame_pos, SEEK_SET) < 0)
209  return -1;
210 
211  av_free_packet(&yop->video_packet);
212  yop->odd_frame = timestamp & 1;
213 
214  return 0;
215 }
216 
218  .name = "yop",
219  .long_name = NULL_IF_CONFIG_SMALL("Psygnosis YOP"),
220  .priv_data_size = sizeof(YopDecContext),
226  .extensions = "yop",
228 };
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition: aviobuf.c:261
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
static int yop_read_header(AVFormatContext *s)
static int yop_read_close(AVFormatContext *s)
int64_t pos
byte position in stream, -1 if unknown
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition: avpacket.c:97
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition: libcdio.c:153
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:709
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
#define AV_RL16
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:256
int64_t data_offset
offset of the first packet
Definition: avformat.h:1242
static AVStream * video_stream
Definition: demuxing.c:39
Format I/O context.
Definition: avformat.h:944
static AVPacket pkt
Definition: demuxing.c:56
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
uint8_t * data
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
#define AV_RB16
struct yop_dec_context YopDecContext
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
#define FFMAX(a, b)
Definition: common.h:56
int flags
A combination of AV_PKT_FLAG values.
uint64_t channel_layout
Audio channel layout.
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
static int yop_read_packet(AVFormatContext *s, AVPacket *pkt)
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
static int yop_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
struct AVRational AVRational
rational number numerator/denominator
int bit_rate
the average bitrate
audio channel layout utility functions
#define FFMIN(a, b)
Definition: common.h:58
static int read_probe(AVProbeData *pd)
ret
Definition: avfilter.c:821
int width
picture width / height.
AVInputFormat ff_yop_demuxer
static AVStream * audio_stream
Definition: demuxing.c:39
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:517
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
AVPacket video_packet
enum AVMediaType codec_type
enum AVCodecID codec_id
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
main external API structure.
static int yop_probe(AVProbeData *probe_packet)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
Definition: libcdio.c:114
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:353
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:563
Main libavformat public API header.
static int frame_count
Definition: muxing.c:234
int channels
number of audio channels
void * priv_data
Format private data.
Definition: avformat.h:964
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.