FFmpeg
amvenc.c
Go to the documentation of this file.
1 /*
2  * AMV muxer
3  *
4  * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com)
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 #include "avformat.h"
23 #include "riff.h"
24 #include "internal.h"
25 #include "avio_internal.h"
26 #include "libavutil/intreadwrite.h"
27 #include "libavutil/avassert.h"
28 
29 /*
30  * Things to note:
31  * - AMV is a hard-coded (and broken) subset of AVI. It's not worth sullying the
32  * existing AVI muxer with its filth.
33  * - No separate demuxer as the existing AVI demuxer can handle these.
34  * - The sizes of certain tags are deliberately set to 0 as some players break
35  * when they're set correctly. Ditto with some header fields.
36  * - There is no index.
37  * - Players are **very** sensitive to the frame order and sizes.
38  * - Frames must be strictly interleaved as V-A, any V-V or A-A will
39  * cause crashes.
40  * - Variable video frame sizes seem to be handled fine.
41  * - Variable audio frame sizes cause crashes.
42  * - If audio is shorter than video, it's padded with silence.
43  * - If video is shorter than audio, the most recent frame is repeated.
44  */
45 
46 #define AMV_STREAM_COUNT 2
47 #define AMV_STREAM_VIDEO 0
48 #define AMV_STREAM_AUDIO 1
49 #define AMV_VIDEO_STRH_SIZE 56
50 #define AMV_VIDEO_STRF_SIZE 36
51 #define AMV_AUDIO_STRH_SIZE 48
52 #define AMV_AUDIO_STRF_SIZE 20 /* sizeof(WAVEFORMATEX) + 2 */
53 
54 typedef struct AMVContext
55 {
56  int64_t riff_start;
57  int64_t movi_list;
58  int64_t offset_duration;
60 
61  int32_t us_per_frame; /* Microseconds per frame. */
62 
63  int32_t aframe_size; /* Expected audio frame size. */
64  int32_t ablock_align; /* Expected audio block align. */
65  AVPacket *apad; /* Dummy audio packet for padding; not owned by us. */
66  AVPacket *vpad; /* Most recent video frame, for padding. */
67 
68  /*
69  * Cumulative PTS values for each stream, used for the final
70  * duration calculcation.
71  */
73 } AMVContext;
74 
75 /* ff_{start,end}_tag(), but sets the size to 0. */
76 static int64_t amv_start_tag(AVIOContext *pb, const char *tag)
77 {
78  ffio_wfourcc(pb, tag);
79  avio_wl32(pb, 0);
80  return avio_tell(pb);
81 }
82 
83 static void amv_end_tag(AVIOContext *pb, int64_t start)
84 {
85  int64_t pos;
86  av_assert0((start&1) == 0);
87 
88  pos = avio_tell(pb);
89  if (pos & 1)
90  avio_w8(pb, 0);
91 }
92 
94 {
95  AMVContext *amv = s->priv_data;
96  AVStream *vst, *ast;
97  int ret;
98 
99  amv->last_stream = -1;
100 
101  if (s->nb_streams != AMV_STREAM_COUNT) {
102  av_log(s, AV_LOG_ERROR, "AMV files only support 2 streams\n");
103  return AVERROR(EINVAL);
104  }
105 
106  vst = s->streams[AMV_STREAM_VIDEO];
107  ast = s->streams[AMV_STREAM_AUDIO];
108 
109  if (vst->codecpar->codec_id != AV_CODEC_ID_AMV) {
110  av_log(s, AV_LOG_ERROR, "First AMV stream must be %s\n",
112  return AVERROR(EINVAL);
113  }
114 
116  av_log(s, AV_LOG_ERROR, "Second AMV stream must be %s\n",
118  return AVERROR(EINVAL);
119  }
120 
121  /* These files are broken-enough as they are. They shouldn't be streamed. */
122  if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
123  av_log(s, AV_LOG_ERROR, "Stream not seekable, unable to write output file\n");
124  return AVERROR(EINVAL);
125  }
126 
129  amv->ablock_align = 8 + (FFALIGN(amv->aframe_size, 2) / 2);
130 
131  av_log(s, AV_LOG_TRACE, "us_per_frame = %d\n", amv->us_per_frame);
132  av_log(s, AV_LOG_TRACE, "aframe_size = %d\n", amv->aframe_size);
133  av_log(s, AV_LOG_TRACE, "ablock_align = %d\n", amv->ablock_align);
134 
135  /*
136  * Bail if the framerate's too high. Prevents the audio frame size from
137  * getting too small. 63fps is the closest value to 60fps that divides
138  * cleanly, so cap it there.
139  */
140  if (amv->us_per_frame < 15873) {
141  av_log(s, AV_LOG_ERROR, "Refusing to mux >63fps video\n");
142  return AVERROR(EINVAL);
143  }
144 
145  /*
146  * frame_size will be set if coming from the encoder.
147  * Make sure the its been configured correctly. The audio frame duration
148  * needs to match that of the video.
149  */
150  if (ast->codecpar->frame_size) {
151  AVCodecParameters *par = ast->codecpar;
152  int bad = 0;
153 
154  if (par->frame_size != amv->aframe_size) {
155  av_log(s, AV_LOG_ERROR, "Invalid audio frame size. Got %d, wanted %d\n",
156  par->frame_size, amv->aframe_size);
157  bad = 1;
158  }
159 
160  if (par->block_align != amv->ablock_align) {
161  av_log(s, AV_LOG_ERROR, "Invalid audio block align. Got %d, wanted %d\n",
162  par->block_align, amv->ablock_align);
163  bad = 1;
164  }
165 
166  if (bad) {
167  av_log(s, AV_LOG_ERROR, "Try -block_size %d\n", amv->aframe_size);
168  return AVERROR(EINVAL);
169  }
170 
171  if (ast->codecpar->sample_rate % amv->aframe_size) {
172  av_log(s, AV_LOG_ERROR, "Audio sample rate not a multiple of the frame size.\n"
173  "Please change video frame rate. Suggested rates: 10,14,15,18,21,25,30\n");
174  return AVERROR(EINVAL);
175  }
176  } else {
177  /* If remuxing from the same source, then this will match the video. */
179  if (aus != amv->us_per_frame) {
180  av_log(s, AV_LOG_ERROR, "Cannot remux streams with a different time base\n");
181  return AVERROR(EINVAL);
182  }
183  }
184 
185  /* Allocate and fill dummy packet so we can pad the audio. */
186  amv->apad = ffformatcontext(s)->pkt;
187  if ((ret = av_new_packet(amv->apad, amv->ablock_align)) < 0) {
188  return ret;
189  }
190 
192  memset(amv->apad->data, 0, amv->ablock_align);
193  AV_WL32(amv->apad->data + 4, amv->aframe_size);
194 
195  amv->vpad = av_packet_alloc();
196  if (!amv->vpad) {
197  return AVERROR(ENOMEM);
198  }
200  amv->vpad->duration = 1;
201  return 0;
202 }
203 
205 {
206  AMVContext *amv = s->priv_data;
207 
208  av_packet_free(&amv->vpad);
209 }
210 
212 {
213  int64_t tag_list, tag_str;
214 
216 
217  tag_list = amv_start_tag(s->pb, "LIST");
218  ffio_wfourcc(s->pb, "strl");
219  tag_str = ff_start_tag(s->pb, "strh");
221  ff_end_tag(s->pb, tag_str);
222 
223  tag_str = ff_start_tag(s->pb, "strf");
225  ff_end_tag(s->pb, tag_str);
226 
227  amv_end_tag(s->pb, tag_list);
228 }
229 
231 {
232  uint8_t buf[AMV_AUDIO_STRF_SIZE];
233  AVIOContext *pb = s->pb;
234  int64_t tag_list, tag_str;
235 
237 
238  tag_list = amv_start_tag(pb, "LIST");
239  ffio_wfourcc(pb, "strl");
240  tag_str = ff_start_tag(pb, "strh");
242  ff_end_tag(pb, tag_str);
243 
244  /* Bodge an (incorrect) WAVEFORMATEX (+2 pad bytes) */
245  tag_str = ff_start_tag(pb, "strf");
246  AV_WL16(buf + 0, 1);
247  AV_WL16(buf + 2, par->channels);
248  AV_WL32(buf + 4, par->sample_rate);
249  AV_WL32(buf + 8, par->sample_rate * par->channels * 2);
250  AV_WL16(buf + 12, 2);
251  AV_WL16(buf + 14, 16);
252  AV_WL16(buf + 16, 0);
253  AV_WL16(buf + 18, 0);
255  ff_end_tag(pb, tag_str);
256 
257  amv_end_tag(pb, tag_list);
258 }
259 
261 {
262  AMVContext *amv = s->priv_data;
263  AVIOContext *pb = s->pb;
264  AVStream *vst = s->streams[AMV_STREAM_VIDEO];
265  AVStream *ast = s->streams[AMV_STREAM_AUDIO];
266  uint8_t amvh[56] = {0};
267  int64_t list1;
268 
269  amv->riff_start = amv_start_tag(pb, "RIFF");
270  ffio_wfourcc(pb, "AMV ");
271  list1 = amv_start_tag(pb, "LIST");
272  ffio_wfourcc(pb, "hdrl");
273 
274  ffio_wfourcc(pb, "amvh");
275  avio_wl32(pb, 56);
276 
277  AV_WL32(amvh + 0, amv->us_per_frame);
278  AV_WL32(amvh + 32, vst->codecpar->width);
279  AV_WL32(amvh + 36, vst->codecpar->height);
280  AV_WL32(amvh + 40, vst->time_base.den);
281  AV_WL32(amvh + 44, vst->time_base.num);
282  AV_WL32(amvh + 48, 0);
283  AV_WL32(amvh + 52, 0); /* duration, filled in later. */
284 
285  avio_write(pb, amvh, sizeof(amvh));
286  amv->offset_duration = avio_tell(pb) - 4;
287 
288  amv_write_vlist(s, vst->codecpar);
289  amv_write_alist(s, ast->codecpar);
290  amv_end_tag(pb, list1);
291 
292  amv->movi_list = amv_start_tag(pb, "LIST");
293  ffio_wfourcc(pb, "movi");
294  return 0;
295 }
296 
298 {
299  AMVContext *amv = s->priv_data;
300 
302  ffio_wfourcc(s->pb, "00dc");
303  else if (pkt->stream_index == AMV_STREAM_AUDIO)
304  ffio_wfourcc(s->pb, "01wb");
305  else
306  av_assert0(0);
307 
308  if (pkt->stream_index == AMV_STREAM_AUDIO && pkt->size != amv->ablock_align) {
309  /* Can happen when remuxing files produced by another encoder. */
310  av_log(s, AV_LOG_WARNING, "Invalid audio packet size (%d != %d)\n",
311  pkt->size, amv->ablock_align);
312  }
313 
314  avio_wl32(s->pb, pkt->size);
315  avio_write(s->pb, pkt->data, pkt->size);
316 
317  amv->lastpts[pkt->stream_index] += pkt->duration;
318  amv->last_stream = pkt->stream_index;
319  return 0;
320 }
321 
323 {
324  AMVContext *amv = s->priv_data;
325  int stream_index = pkt->stream_index;
326 
327  if (stream_index != amv->last_stream)
328  return 0;
329 
330  stream_index = (stream_index + 1) % s->nb_streams;
331  if (stream_index == AMV_STREAM_VIDEO)
332  return amv_write_packet_internal(s, amv->vpad);
333  else if (stream_index == AMV_STREAM_AUDIO)
334  return amv_write_packet_internal(s, amv->apad);
335  else
336  av_assert0(0);
337 
338  return AVERROR(EINVAL);
339 }
340 
342 {
343  AMVContext *amv = s->priv_data;
344  int ret;
345 
346  /* Add a dummy frame if we've received two of the same index. */
347  if ((ret = amv_pad(s, pkt)) < 0)
348  return ret;
349 
350  if ((ret = amv_write_packet_internal(s, pkt)) < 0)
351  return ret;
352 
354  /* Save the last packet for padding. */
355  av_packet_unref(amv->vpad);
356  if ((ret = av_packet_ref(amv->vpad, pkt)) < 0)
357  return ret;
358  }
359 
360  return 0;
361 }
362 
364 {
365  AMVContext *amv = s->priv_data;
366  AVStream *vst = s->streams[AMV_STREAM_VIDEO];
367  AVStream *ast = s->streams[AMV_STREAM_AUDIO];
368  int64_t maxpts, ret;
369  int hh, mm, ss;
370 
371  /* Pad-out one last audio frame if needed. */
372  if (amv->last_stream == AMV_STREAM_VIDEO) {
373  if ((ret = amv_write_packet_internal(s, amv->apad)) < 0)
374  return ret;
375  }
376 
377  amv_end_tag(s->pb, amv->movi_list);
378  amv_end_tag(s->pb, amv->riff_start);
379 
380  ffio_wfourcc(s->pb, "AMV_");
381  ffio_wfourcc(s->pb, "END_");
382 
383  if ((ret = avio_seek(s->pb, amv->offset_duration, SEEK_SET)) < 0)
384  return ret;
385 
386  /* Go back and write the duration. */
387  maxpts = FFMAX(
390  );
391 
392  ss = maxpts / AV_TIME_BASE;
393  mm = ss / 60;
394  hh = mm / 60;
395  ss %= 60;
396  mm %= 60;
397 
398  avio_w8(s->pb, ss);
399  avio_w8(s->pb, mm);
400  avio_wl16(s->pb, hh);
401  return 0;
402 }
403 
405  .name = "amv",
406  .long_name = NULL_IF_CONFIG_SMALL("AMV"),
407  .mime_type = "video/amv",
408  .extensions = "amv",
409  .priv_data_size = sizeof(AMVContext),
410  .audio_codec = AV_CODEC_ID_ADPCM_IMA_AMV,
411  .video_codec = AV_CODEC_ID_AMV,
412  .init = amv_init,
413  .deinit = amv_deinit,
417 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:424
AMVContext::lastpts
int64_t lastpts[AMV_STREAM_COUNT]
Definition: amvenc.c:72
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVOutputFormat::name
const char * name
Definition: avformat.h:504
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame 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. Frame references ownership and permissions
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
ffio_wfourcc
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:116
AMV_STREAM_VIDEO
#define AMV_STREAM_VIDEO
Definition: amvenc.c:47
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: codec_par.h:52
ffformatcontext
static av_always_inline FFFormatContext * ffformatcontext(AVFormatContext *s)
Definition: internal.h:189
AMV_STREAM_COUNT
#define AMV_STREAM_COUNT
Definition: amvenc.c:46
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
amv_start_tag
static int64_t amv_start_tag(AVIOContext *pb, const char *tag)
Definition: amvenc.c:76
deinit
static void deinit(AVFormatContext *s)
Definition: chromaprint.c:50
amv_deinit
static void amv_deinit(AVFormatContext *s)
Definition: amvenc.c:204
AVPacket::data
uint8_t * data
Definition: packet.h:373
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:391
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AMV_STREAM_AUDIO
#define AMV_STREAM_AUDIO
Definition: amvenc.c:48
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:75
amv_pad
static int amv_pad(AVFormatContext *s, AVPacket *pkt)
Definition: amvenc.c:322
AMV_VIDEO_STRF_SIZE
#define AMV_VIDEO_STRF_SIZE
Definition: amvenc.c:50
ff_amv_muxer
const AVOutputFormat ff_amv_muxer
Definition: amvenc.c:404
init
static int init
Definition: av_tx.c:47
avio_wl16
void avio_wl16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:466
AVCodecParameters::channels
int channels
Audio only.
Definition: codec_par.h:166
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:504
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:261
AVRational::num
int num
Numerator.
Definition: rational.h:59
amv_write_vlist
static void amv_write_vlist(AVFormatContext *s, AVCodecParameters *par)
Definition: amvenc.c:211
ff_start_tag
int64_t ff_start_tag(AVIOContext *pb, const char *tag)
Definition: riffenc.c:32
avassert.h
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:206
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AVCodecParameters::frame_size
int frame_size
Audio only.
Definition: codec_par.h:181
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
av_new_packet
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:99
AMVContext::vpad
AVPacket * vpad
Definition: amvenc.c:66
amv_init
static av_cold int amv_init(AVFormatContext *s)
Definition: amvenc.c:93
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:126
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:141
amv_write_packet
static int amv_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: amvenc.c:341
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1200
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1095
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:965
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:98
AMV_AUDIO_STRF_SIZE
#define AMV_AUDIO_STRF_SIZE
Definition: amvenc.c:52
AV_CODEC_ID_ADPCM_IMA_AMV
@ AV_CODEC_ID_ADPCM_IMA_AMV
Definition: codec_id.h:372
avio_w8
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:210
ffio_fill
void ffio_fill(AVIOContext *s, int b, int64_t count)
Definition: aviobuf.c:218
AMV_AUDIO_STRH_SIZE
#define AMV_AUDIO_STRH_SIZE
Definition: amvenc.c:51
av_packet_ref
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:432
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:170
AMVContext::us_per_frame
int32_t us_per_frame
Definition: amvenc.c:61
amv_write_packet_internal
static int amv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
Definition: amvenc.c:297
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
AVPacket::size
int size
Definition: packet.h:374
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:232
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
avio_wl32
void avio_wl32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:386
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:64
ff_end_tag
void ff_end_tag(AVIOContext *pb, int64_t start)
Definition: riffenc.c:39
write_packet
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:727
avcodec_get_name
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition: utils.c:443
AVOutputFormat
Definition: avformat.h:503
avio_internal.h
AMVContext::offset_duration
int64_t offset_duration
Definition: amvenc.c:58
AVCodecParameters::height
int height
Definition: codec_par.h:127
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
AVCodecParameters::block_align
int block_align
Audio only.
Definition: codec_par.h:177
AMVContext::riff_start
int64_t riff_start
Definition: amvenc.c:56
AMVContext::last_stream
int last_stream
Definition: amvenc.c:59
AMVContext::movi_list
int64_t movi_list
Definition: amvenc.c:57
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:128
tag
uint32_t tag
Definition: movenc.c:1596
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:935
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:260
pos
unsigned int pos
Definition: spdifenc.c:412
avformat.h
amv_write_trailer
static int amv_write_trailer(AVFormatContext *s)
Definition: amvenc.c:363
AV_CODEC_ID_AMV
@ AV_CODEC_ID_AMV
Definition: codec_id.h:157
AVIO_SEEKABLE_NORMAL
#define AVIO_SEEKABLE_NORMAL
Seeking works like for a local file.
Definition: avio.h:40
AVRational::den
int den
Denominator.
Definition: rational.h:60
amv_write_header
static int amv_write_header(AVFormatContext *s)
Definition: amvenc.c:260
AVPacket::stream_index
int stream_index
Definition: packet.h:375
AMVContext::ablock_align
int32_t ablock_align
Definition: amvenc.c:64
bad
static int bad(InterplayACMContext *s, unsigned ind, unsigned col)
Definition: interplayacm.c:126
AMVContext::aframe_size
int32_t aframe_size
Definition: amvenc.c:63
FFFormatContext::pkt
AVPacket * pkt
Used to hold temporary packets for the generic demuxing code.
Definition: internal.h:132
tag_list
static const struct exif_tag tag_list[]
Definition: exif.h:43
AMV_VIDEO_STRH_SIZE
#define AMV_VIDEO_STRH_SIZE
Definition: amvenc.c:49
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
AVPacket
This structure stores compressed data.
Definition: packet.h:350
riff.h
int32_t
int32_t
Definition: audioconvert.c:56
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AMVContext::apad
AVPacket * apad
Definition: amvenc.c:65
amv_write_alist
static void amv_write_alist(AVFormatContext *s, AVCodecParameters *par)
Definition: amvenc.c:230
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:347
amv_end_tag
static void amv_end_tag(AVIOContext *pb, int64_t start)
Definition: amvenc.c:83
AMVContext
Definition: amvenc.c:54