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. */
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 = av_packet_alloc();
187  if (!amv->apad)
188  return AVERROR(ENOMEM);
189  if ((ret = av_new_packet(amv->apad, amv->ablock_align)) < 0) {
190  return ret;
191  }
192 
194  memset(amv->apad->data, 0, amv->ablock_align);
195  AV_WL32(amv->apad->data + 4, amv->aframe_size);
196 
197  amv->vpad = av_packet_alloc();
198  if (!amv->vpad) {
199  return AVERROR(ENOMEM);
200  }
202  amv->vpad->duration = 1;
203  return 0;
204 }
205 
207 {
208  AMVContext *amv = s->priv_data;
209 
210  av_packet_free(&amv->apad);
211  av_packet_free(&amv->vpad);
212 }
213 
215 {
216  int64_t tag_list, tag_str;
217 
219 
220  tag_list = amv_start_tag(s->pb, "LIST");
221  ffio_wfourcc(s->pb, "strl");
222  tag_str = ff_start_tag(s->pb, "strh");
224  ff_end_tag(s->pb, tag_str);
225 
226  tag_str = ff_start_tag(s->pb, "strf");
228  ff_end_tag(s->pb, tag_str);
229 
230  amv_end_tag(s->pb, tag_list);
231 }
232 
234 {
235  uint8_t buf[AMV_AUDIO_STRF_SIZE];
236  AVIOContext *pb = s->pb;
237  int64_t tag_list, tag_str;
238 
240 
241  tag_list = amv_start_tag(pb, "LIST");
242  ffio_wfourcc(pb, "strl");
243  tag_str = ff_start_tag(pb, "strh");
245  ff_end_tag(pb, tag_str);
246 
247  /* Bodge an (incorrect) WAVEFORMATEX (+2 pad bytes) */
248  tag_str = ff_start_tag(pb, "strf");
249  AV_WL16(buf + 0, 1);
250  AV_WL16(buf + 2, par->channels);
251  AV_WL32(buf + 4, par->sample_rate);
252  AV_WL32(buf + 8, par->sample_rate * par->channels * 2);
253  AV_WL16(buf + 12, 2);
254  AV_WL16(buf + 14, 16);
255  AV_WL16(buf + 16, 0);
256  AV_WL16(buf + 18, 0);
258  ff_end_tag(pb, tag_str);
259 
260  amv_end_tag(pb, tag_list);
261 }
262 
264 {
265  AMVContext *amv = s->priv_data;
266  AVIOContext *pb = s->pb;
267  AVStream *vst = s->streams[AMV_STREAM_VIDEO];
268  AVStream *ast = s->streams[AMV_STREAM_AUDIO];
269  uint8_t amvh[56] = {0};
270  int64_t list1;
271 
272  amv->riff_start = amv_start_tag(pb, "RIFF");
273  ffio_wfourcc(pb, "AMV ");
274  list1 = amv_start_tag(pb, "LIST");
275  ffio_wfourcc(pb, "hdrl");
276 
277  ffio_wfourcc(pb, "amvh");
278  avio_wl32(pb, 56);
279 
280  AV_WL32(amvh + 0, amv->us_per_frame);
281  AV_WL32(amvh + 32, vst->codecpar->width);
282  AV_WL32(amvh + 36, vst->codecpar->height);
283  AV_WL32(amvh + 40, vst->time_base.den);
284  AV_WL32(amvh + 44, vst->time_base.num);
285  AV_WL32(amvh + 48, 0);
286  AV_WL32(amvh + 52, 0); /* duration, filled in later. */
287 
288  avio_write(pb, amvh, sizeof(amvh));
289  amv->offset_duration = avio_tell(pb) - 4;
290 
291  amv_write_vlist(s, vst->codecpar);
292  amv_write_alist(s, ast->codecpar);
293  amv_end_tag(pb, list1);
294 
295  amv->movi_list = amv_start_tag(pb, "LIST");
296  ffio_wfourcc(pb, "movi");
297  return 0;
298 }
299 
301 {
302  AMVContext *amv = s->priv_data;
303 
305  ffio_wfourcc(s->pb, "00dc");
306  else if (pkt->stream_index == AMV_STREAM_AUDIO)
307  ffio_wfourcc(s->pb, "01wb");
308  else
309  av_assert0(0);
310 
311  if (pkt->stream_index == AMV_STREAM_AUDIO && pkt->size != amv->ablock_align) {
312  /* Can happen when remuxing files produced by another encoder. */
313  av_log(s, AV_LOG_WARNING, "Invalid audio packet size (%d != %d)\n",
314  pkt->size, amv->ablock_align);
315  }
316 
317  avio_wl32(s->pb, pkt->size);
318  avio_write(s->pb, pkt->data, pkt->size);
319 
320  amv->lastpts[pkt->stream_index] += pkt->duration;
321  amv->last_stream = pkt->stream_index;
322  return 0;
323 }
324 
326 {
327  AMVContext *amv = s->priv_data;
328  int stream_index = pkt->stream_index;
329 
330  if (stream_index != amv->last_stream)
331  return 0;
332 
333  stream_index = (stream_index + 1) % s->nb_streams;
334  if (stream_index == AMV_STREAM_VIDEO)
335  return amv_write_packet_internal(s, amv->vpad);
336  else if (stream_index == AMV_STREAM_AUDIO)
337  return amv_write_packet_internal(s, amv->apad);
338  else
339  av_assert0(0);
340 
341  return AVERROR(EINVAL);
342 }
343 
345 {
346  AMVContext *amv = s->priv_data;
347  int ret;
348 
349  /* Add a dummy frame if we've received two of the same index. */
350  if ((ret = amv_pad(s, pkt)) < 0)
351  return ret;
352 
353  if ((ret = amv_write_packet_internal(s, pkt)) < 0)
354  return ret;
355 
357  /* Save the last packet for padding. */
358  av_packet_unref(amv->vpad);
359  if ((ret = av_packet_ref(amv->vpad, pkt)) < 0)
360  return ret;
361  }
362 
363  return 0;
364 }
365 
367 {
368  AMVContext *amv = s->priv_data;
369  AVStream *vst = s->streams[AMV_STREAM_VIDEO];
370  AVStream *ast = s->streams[AMV_STREAM_AUDIO];
371  int64_t maxpts, ret;
372  int hh, mm, ss;
373 
374  /* Pad-out one last audio frame if needed. */
375  if (amv->last_stream == AMV_STREAM_VIDEO) {
376  if ((ret = amv_write_packet_internal(s, amv->apad)) < 0)
377  return ret;
378  }
379 
380  amv_end_tag(s->pb, amv->movi_list);
381  amv_end_tag(s->pb, amv->riff_start);
382 
383  ffio_wfourcc(s->pb, "AMV_");
384  ffio_wfourcc(s->pb, "END_");
385 
386  if ((ret = avio_seek(s->pb, amv->offset_duration, SEEK_SET)) < 0)
387  return ret;
388 
389  /* Go back and write the duration. */
390  maxpts = FFMAX(
393  );
394 
395  ss = maxpts / AV_TIME_BASE;
396  mm = ss / 60;
397  hh = mm / 60;
398  ss %= 60;
399  mm %= 60;
400 
401  avio_w8(s->pb, ss);
402  avio_w8(s->pb, mm);
403  avio_wl16(s->pb, hh);
404  return 0;
405 }
406 
408  .name = "amv",
409  .long_name = NULL_IF_CONFIG_SMALL("AMV"),
410  .mime_type = "video/amv",
411  .extensions = "amv",
412  .priv_data_size = sizeof(AMVContext),
413  .audio_codec = AV_CODEC_ID_ADPCM_IMA_AMV,
414  .video_codec = AV_CODEC_ID_AMV,
415  .init = amv_init,
416  .deinit = amv_deinit,
420 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:404
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
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
AVOutputFormat::name
const char * name
Definition: avformat.h:496
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:58
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
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
amv_deinit
static void amv_deinit(AVFormatContext *s)
Definition: amvenc.c:206
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
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:70
amv_pad
static int amv_pad(AVFormatContext *s, AVPacket *pkt)
Definition: amvenc.c:325
AMV_VIDEO_STRF_SIZE
#define AMV_VIDEO_STRF_SIZE
Definition: amvenc.c:50
ff_amv_muxer
const AVOutputFormat ff_amv_muxer
Definition: amvenc.c:407
avio_wl16
void avio_wl16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:445
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:538
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:214
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:94
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:344
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1107
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:994
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:870
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:371
avio_w8
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:193
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:411
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:300
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:116
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:215
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
avio_wl32
void avio_wl32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:365
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:59
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:729
avcodec_get_name
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition: utils.c:448
AVOutputFormat
Definition: avformat.h:495
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:1594
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:847
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:243
pos
unsigned int pos
Definition: spdifenc.c:412
avformat.h
amv_write_trailer
static int amv_write_trailer(AVFormatContext *s)
Definition: amvenc.c:366
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:263
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:122
AMVContext::aframe_size
int32_t aframe_size
Definition: amvenc.c:63
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:48
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
ffio_fill
void ffio_fill(AVIOContext *s, int b, int count)
Definition: aviobuf.c:201
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:233
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