FFmpeg
nsvdec.c
Go to the documentation of this file.
1 /*
2  * NSV demuxer
3  * Copyright (c) 2004 The FFmpeg Project
4  *
5  * first version by Francois Revol <revol@free.fr>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include "libavutil/attributes.h"
25 #include "libavutil/mathematics.h"
26 #include "libavutil/mem.h"
27 #include "avformat.h"
28 #include "demux.h"
29 #include "internal.h"
30 #include "libavutil/dict.h"
31 #include "libavutil/intreadwrite.h"
32 
33 /* max bytes to crawl for trying to resync
34  * stupid streaming servers don't start at chunk boundaries...
35  */
36 #define NSV_MAX_RESYNC (500*1024)
37 #define NSV_MAX_RESYNC_TRIES 300
38 
39 /*
40  * References:
41  * (1) http://www.multimedia.cx/nsv-format.txt
42  * seems someone came to the same conclusions as me, and updated it:
43  * (2) http://www.stud.ktu.lt/~vitslav/nsv/nsv-format.txt
44  * http://www.stud.ktu.lt/~vitslav/nsv/
45  * official docs
46  * (3) http://ultravox.aol.com/NSVFormat.rtf
47  * Sample files:
48  * (S1) http://www.nullsoft.com/nsv/samples/
49  * http://www.nullsoft.com/nsv/samples/faster.nsv
50  * http://streamripper.sourceforge.net/openbb/read.php?TID=492&page=4
51  */
52 
53 /*
54  * notes on the header (Francois Revol):
55  *
56  * It is followed by strings, then a table, but nothing tells
57  * where the table begins according to (1). After checking faster.nsv,
58  * I believe NVSf[16-19] gives the size of the strings data
59  * (that is the offset of the data table after the header).
60  * After checking all samples from (S1) all confirms this.
61  *
62  * Then, about NSVf[12-15], faster.nsf has 179700. When viewing it in VLC,
63  * I noticed there was about 1 NVSs chunk/s, so I ran
64  * strings faster.nsv | grep NSVs | wc -l
65  * which gave me 180. That leads me to think that NSVf[12-15] might be the
66  * file length in milliseconds.
67  * Let's try that:
68  * for f in *.nsv; do HTIME="$(od -t x4 "$f" | head -1 | sed 's/.* //')"; echo "'$f' $((0x$HTIME))s = $((0x$HTIME/1000/60)):$((0x$HTIME/1000%60))"; done
69  * except for nsvtrailer (which doesn't have an NSVf header), it reports correct time.
70  *
71  * nsvtrailer.nsv (S1) does not have any NSVf header, only NSVs chunks,
72  * so the header seems to not be mandatory. (for streaming).
73  *
74  * index slice duration check (excepts nsvtrailer.nsv):
75  * for f in [^n]*.nsv; do DUR="$(ffmpeg -i "$f" 2>/dev/null | grep 'NSVf duration' | cut -d ' ' -f 4)"; IC="$(ffmpeg -i "$f" 2>/dev/null | grep 'INDEX ENTRIES' | cut -d ' ' -f 2)"; echo "duration $DUR, slite time $(($DUR/$IC))"; done
76  */
77 
78 /*
79  * TODO:
80  * - handle timestamps !!!
81  * - use index
82  * - mime-type in probe()
83  * - seek
84  */
85 
86 #if 0
87 struct NSVf_header {
88  uint32_t chunk_tag; /* 'NSVf' */
89  uint32_t chunk_size;
90  uint32_t file_size; /* max 4GB ??? no one learns anything it seems :^) */
91  uint32_t file_length; //unknown1; /* what about MSB of file_size ? */
92  uint32_t info_strings_size; /* size of the info strings */ //unknown2;
93  uint32_t table_entries;
94  uint32_t table_entries_used; /* the left ones should be -1 */
95 };
96 
97 struct NSVs_header {
98  uint32_t chunk_tag; /* 'NSVs' */
99  uint32_t v4cc; /* or 'NONE' */
100  uint32_t a4cc; /* or 'NONE' */
101  uint16_t vwidth; /* av_assert0(vwidth%16==0) */
102  uint16_t vheight; /* av_assert0(vheight%16==0) */
103  uint8_t framerate; /* value = (framerate&0x80)?frtable[frameratex0x7f]:framerate */
104  uint16_t unknown;
105 };
106 
107 struct nsv_avchunk_header {
108  uint8_t vchunk_size_lsb;
109  uint16_t vchunk_size_msb; /* value = (vchunk_size_msb << 4) | (vchunk_size_lsb >> 4) */
110  uint16_t achunk_size;
111 };
112 
113 struct nsv_pcm_header {
114  uint8_t bits_per_sample;
115  uint8_t channel_count;
116  uint16_t sample_rate;
117 };
118 #endif
119 
120 /* variation from avi.h */
121 /*typedef struct CodecTag {
122  int id;
123  unsigned int tag;
124 } CodecTag;*/
125 
126 /* tags */
127 
128 #define T_NSVF MKTAG('N', 'S', 'V', 'f') /* file header */
129 #define T_NSVS MKTAG('N', 'S', 'V', 's') /* chunk header */
130 #define T_TOC2 MKTAG('T', 'O', 'C', '2') /* extra index marker */
131 #define T_NONE MKTAG('N', 'O', 'N', 'E') /* null a/v 4CC */
132 #define T_SUBT MKTAG('S', 'U', 'B', 'T') /* subtitle aux data */
133 #define T_ASYN MKTAG('A', 'S', 'Y', 'N') /* async a/v aux marker */
134 #define T_KEYF MKTAG('K', 'E', 'Y', 'F') /* video keyframe aux marker (addition) */
135 
136 #define TB_NSVF MKBETAG('N', 'S', 'V', 'f')
137 #define TB_NSVS MKBETAG('N', 'S', 'V', 's')
138 
139 /* hardcoded stream indexes */
140 #define NSV_ST_VIDEO 0
141 #define NSV_ST_AUDIO 1
142 #define NSV_ST_SUBT 2
143 
144 enum NSVStatus {
153 };
154 
155 typedef struct NSVStream {
156  int frame_offset; /* current frame (video) or byte (audio) counter
157  (used to compute the pts) */
158  int scale;
159  int rate;
160  int sample_size; /* audio only data */
161  int start;
162 
163  int new_frame_offset; /* temporary storage (used during seek) */
164  int cum_len; /* temporary storage (used during seek) */
165 } NSVStream;
166 
167 typedef struct NSVContext {
169  int NSVf_end;
170  uint32_t *nsvs_file_offset;
173  AVPacket ahead[2]; /* [v, a] if .data is !NULL there is something */
174  /* cached */
175  int64_t duration;
176  uint32_t vtag, atag;
177  uint16_t vwidth, vheight;
178  int16_t avsync;
180  uint32_t *nsvs_timestamps;
181  int nsvf;
182 } NSVContext;
183 
185  { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
186  { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
187  { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
188  { AV_CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
189  { AV_CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
190  { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
191  { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
192  { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
193  { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
194  { AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') },
195 /*
196  { AV_CODEC_ID_VP4, MKTAG('V', 'P', '4', ' ') },
197  { AV_CODEC_ID_VP4, MKTAG('V', 'P', '4', '0') },
198 */
199  { AV_CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') }, /* cf sample xvid decoder from nsv_codec_sdk.zip */
200  { AV_CODEC_ID_H264, MKTAG('H', '2', '6', '4') },
201  { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
202  { AV_CODEC_ID_NONE, 0 },
203 };
204 
206  { AV_CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
207  { AV_CODEC_ID_AAC, MKTAG('A', 'A', 'C', ' ') },
208  { AV_CODEC_ID_AAC, MKTAG('A', 'A', 'C', 'P') },
209  { AV_CODEC_ID_AAC, MKTAG('A', 'A', 'V', ' ') },
210  { AV_CODEC_ID_AAC, MKTAG('V', 'L', 'B', ' ') },
211  { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', ' ') },
212  { AV_CODEC_ID_PCM_U16LE, MKTAG('P', 'C', 'M', ' ') },
213  { AV_CODEC_ID_NONE, 0 },
214 };
215 
216 //static int nsv_load_index(AVFormatContext *s);
217 static int nsv_read_chunk(AVFormatContext *s, int fill_header);
218 
219 /* try to find something we recognize, and set the state accordingly */
221 {
222  NSVContext *nsv = s->priv_data;
223  AVIOContext *pb = s->pb;
224  uint32_t v = 0;
225  int i;
226 
227  for (i = 0; i < NSV_MAX_RESYNC; i++) {
228  if (avio_feof(pb)) {
229  av_log(s, AV_LOG_TRACE, "NSV EOF\n");
230  nsv->state = NSV_UNSYNC;
231  return -1;
232  }
233  v <<= 8;
234  v |= avio_r8(pb);
235  if (i < 8) {
236  av_log(s, AV_LOG_TRACE, "NSV resync: [%d] = %02"PRIx32"\n", i, v & 0x0FF);
237  }
238 
239  if ((v & 0x0000ffff) == 0xefbe) { /* BEEF */
240  av_log(s, AV_LOG_TRACE, "NSV resynced on BEEF after %d bytes\n", i+1);
241  nsv->state = NSV_FOUND_BEEF;
242  return 0;
243  }
244  /* we read as big-endian, thus the MK*BE* */
245  if (v == TB_NSVF) { /* NSVf */
246  av_log(s, AV_LOG_TRACE, "NSV resynced on NSVf after %d bytes\n", i+1);
247  nsv->state = NSV_FOUND_NSVF;
248  return 0;
249  }
250  if (v == MKBETAG('N', 'S', 'V', 's')) { /* NSVs */
251  av_log(s, AV_LOG_TRACE, "NSV resynced on NSVs after %d bytes\n", i+1);
252  nsv->state = NSV_FOUND_NSVS;
253  return 0;
254  }
255 
256  }
257  av_log(s, AV_LOG_TRACE, "NSV sync lost\n");
258  return -1;
259 }
260 
262 {
263  NSVContext *nsv = s->priv_data;
264  AVIOContext *pb = s->pb;
265  unsigned int av_unused file_size;
266  unsigned int size;
267  int64_t duration;
268  int strings_size;
269  int table_entries;
270  int table_entries_used;
271 
272  nsv->state = NSV_UNSYNC; /* in case we fail */
273 
274  if (nsv->nsvf) {
275  av_log(s, AV_LOG_TRACE, "Multiple NSVf\n");
276  return 0;
277  }
278  nsv->nsvf = 1;
279 
280  size = avio_rl32(pb);
281  if (size < 28)
282  return -1;
283  nsv->NSVf_end = size;
284 
285  file_size = (uint32_t)avio_rl32(pb);
286  av_log(s, AV_LOG_TRACE, "NSV NSVf chunk_size %u\n", size);
287  av_log(s, AV_LOG_TRACE, "NSV NSVf file_size %u\n", file_size);
288 
289  nsv->duration = duration = avio_rl32(pb); /* in ms */
290  av_log(s, AV_LOG_TRACE, "NSV NSVf duration %"PRId64" ms\n", duration);
291  // XXX: store it in AVStreams
292 
293  strings_size = avio_rl32(pb);
294  table_entries = avio_rl32(pb);
295  table_entries_used = avio_rl32(pb);
296  av_log(s, AV_LOG_TRACE, "NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",
297  strings_size, table_entries, table_entries_used);
298  if (avio_feof(pb))
299  return -1;
300 
301  av_log(s, AV_LOG_TRACE, "NSV got header; filepos %"PRId64"\n", avio_tell(pb));
302 
303  if (strings_size > 0) {
304  char *strings; /* last byte will be '\0' to play safe with str*() */
305  char *p, *endp;
306  char *token, *value;
307  char quote;
308 
309  p = strings = av_mallocz((size_t)strings_size + 1);
310  if (!p)
311  return AVERROR(ENOMEM);
312  endp = strings + strings_size;
313  avio_read(pb, strings, strings_size);
314  while (p < endp) {
315  while (*p == ' ')
316  p++; /* strip out spaces */
317  if (p >= endp-2)
318  break;
319  token = p;
320  p = strchr(p, '=');
321  if (!p || p >= endp-2)
322  break;
323  *p++ = '\0';
324  quote = *p++;
325  value = p;
326  p = strchr(p, quote);
327  if (!p || p >= endp)
328  break;
329  *p++ = '\0';
330  av_log(s, AV_LOG_TRACE, "NSV NSVf INFO: %s='%s'\n", token, value);
331  av_dict_set(&s->metadata, token, value, 0);
332  }
333  av_free(strings);
334  }
335  if (avio_feof(pb))
336  return -1;
337 
338  av_log(s, AV_LOG_TRACE, "NSV got infos; filepos %"PRId64"\n", avio_tell(pb));
339 
340  if (table_entries_used > 0) {
341  int i;
342  nsv->index_entries = table_entries_used;
343  if((unsigned)table_entries_used >= UINT_MAX / sizeof(uint32_t))
344  return -1;
345  nsv->nsvs_file_offset = av_malloc_array((unsigned)table_entries_used, sizeof(uint32_t));
346  if (!nsv->nsvs_file_offset)
347  return AVERROR(ENOMEM);
348 
349  for(i=0;i<table_entries_used;i++) {
350  if (avio_feof(pb))
351  return AVERROR_INVALIDDATA;
352  nsv->nsvs_file_offset[i] = avio_rl32(pb) + size;
353  }
354 
355  if(table_entries > table_entries_used &&
356  avio_rl32(pb) == MKTAG('T','O','C','2')) {
357  nsv->nsvs_timestamps = av_malloc_array((unsigned)table_entries_used, sizeof(uint32_t));
358  if (!nsv->nsvs_timestamps)
359  return AVERROR(ENOMEM);
360  for(i=0;i<table_entries_used;i++) {
361  nsv->nsvs_timestamps[i] = avio_rl32(pb);
362  }
363  }
364  }
365 
366  av_log(s, AV_LOG_TRACE, "NSV got index; filepos %"PRId64"\n", avio_tell(pb));
367 
368  avio_seek(pb, nsv->base_offset + size, SEEK_SET); /* required for dumbdriving-271.nsv (2 extra bytes) */
369 
370  if (avio_feof(pb))
371  return -1;
372  nsv->state = NSV_HAS_READ_NSVF;
373  return 0;
374 }
375 
377 {
378  NSVContext *nsv = s->priv_data;
379  AVIOContext *pb = s->pb;
380  uint32_t vtag, atag;
381  uint16_t vwidth, vheight;
383  int i;
384  AVStream *st;
385  NSVStream *nst;
386 
387  vtag = avio_rl32(pb);
388  atag = avio_rl32(pb);
389  vwidth = avio_rl16(pb);
390  vheight = avio_rl16(pb);
391  i = avio_r8(pb);
392 
393  av_log(s, AV_LOG_TRACE, "NSV NSVs framerate code %2x\n", i);
394  if(i&0x80) { /* odd way of giving native framerates from docs */
395  int t=(i & 0x7F)>>2;
396  if(t<16) framerate = (AVRational){1, t+1};
397  else framerate = (AVRational){t-15, 1};
398 
399  if(i&1){
400  framerate.num *= 1000;
401  framerate.den *= 1001;
402  }
403 
404  if((i&3)==3) framerate.num *= 24;
405  else if((i&3)==2) framerate.num *= 25;
406  else framerate.num *= 30;
407  }
408  else
409  framerate= (AVRational){i, 1};
410 
411  nsv->avsync = avio_rl16(pb);
412  nsv->framerate = framerate;
413 
414  av_log(s, AV_LOG_TRACE, "NSV NSVs vsize %dx%d\n", vwidth, vheight);
415 
416  /* XXX change to ap != NULL ? */
417  if (s->nb_streams == 0) { /* streams not yet published, let's do that */
418  nsv->vtag = vtag;
419  nsv->atag = atag;
420  nsv->vwidth = vwidth;
421  nsv->vheight = vwidth;
422  if (vtag != T_NONE) {
423  int i;
424  st = avformat_new_stream(s, NULL);
425  if (!st)
426  goto fail;
427 
428  st->id = NSV_ST_VIDEO;
429  nst = av_mallocz(sizeof(NSVStream));
430  if (!nst)
431  goto fail;
432  st->priv_data = nst;
434  st->codecpar->codec_tag = vtag;
436  st->codecpar->width = vwidth;
437  st->codecpar->height = vheight;
438  st->codecpar->bits_per_coded_sample = 24; /* depth XXX */
439 
440  avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
441  st->start_time = 0;
442  st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
443 
444  for(i=0;i<nsv->index_entries;i++) {
445  if(nsv->nsvs_timestamps) {
447  0, 0, AVINDEX_KEYFRAME);
448  } else {
449  int64_t ts = av_rescale(i*nsv->duration/nsv->index_entries, framerate.num, 1000*framerate.den);
451  }
452  }
453  }
454  if (atag != T_NONE) {
455  st = avformat_new_stream(s, NULL);
456  if (!st)
457  goto fail;
458 
459  st->id = NSV_ST_AUDIO;
460  nst = av_mallocz(sizeof(NSVStream));
461  if (!nst)
462  goto fail;
463  st->priv_data = nst;
465  st->codecpar->codec_tag = atag;
467 
468  if (atag == MKTAG('A', 'A', 'V', ' ')) {
469  static const uint8_t aav_pce[] = {
470  0x12, 0x00, 0x05, 0x08, 0x48, 0x00,
471  0x20, 0x00, 0xC6, 0x40, 0x04, 0x4C,
472  0x61, 0x76, 0x63, 0x56, 0xE5, 0x00,
473  0x00, 0x00,
474  };
475  int ret;
476 
477  if ((ret = ff_alloc_extradata(st->codecpar, sizeof(aav_pce))) < 0)
478  return ret;
479 
480  st->codecpar->sample_rate = 44100;
481  memcpy(st->codecpar->extradata, aav_pce, sizeof(aav_pce));
482  }
483 
484  ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL; /* for PCM we will read a chunk later and put correct info */
485 
486  /* set timebase to common denominator of ms and framerate */
487  avpriv_set_pts_info(st, 64, 1, framerate.num*1000);
488  st->start_time = 0;
489  st->duration = (int64_t)nsv->duration * framerate.num;
490  }
491  } else {
492  if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
493  av_log(s, AV_LOG_TRACE, "NSV NSVs header values differ from the first one!!!\n");
494  //return -1;
495  }
496  }
497 
498  nsv->state = NSV_HAS_READ_NSVS;
499  return 0;
500 fail:
501  /* XXX */
502  nsv->state = NSV_UNSYNC;
503  return -1;
504 }
505 
507 {
508  NSVContext *nsv = s->priv_data;
509  int i, err;
510 
511  nsv->state = NSV_UNSYNC;
512  nsv->ahead[0].data = nsv->ahead[1].data = NULL;
513 
514  for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
515  err = nsv_resync(s);
516  if (err < 0)
517  return err;
518  if (nsv->state == NSV_FOUND_NSVF) {
519  err = nsv_parse_NSVf_header(s);
520  if (err < 0)
521  return err;
522  }
523  /* we need the first NSVs also... */
524  if (nsv->state == NSV_FOUND_NSVS) {
525  err = nsv_parse_NSVs_header(s);
526  if (err < 0)
527  return err;
528  break; /* we just want the first one */
529  }
530  }
531  if (s->nb_streams < 1) /* no luck so far */
532  return AVERROR_INVALIDDATA;
533 
534  /* now read the first chunk, so we can attempt to decode more info */
535  err = nsv_read_chunk(s, 1);
536 
537  av_log(s, AV_LOG_TRACE, "parsed header\n");
538  return err;
539 }
540 
541 static int nsv_read_chunk(AVFormatContext *s, int fill_header)
542 {
543  NSVContext *nsv = s->priv_data;
544  AVIOContext *pb = s->pb;
545  AVStream *st[2] = {NULL, NULL};
546  NSVStream *nst;
547  AVPacket *pkt;
548  int i, err = 0;
549  uint8_t auxcount; /* number of aux metadata, also 4 bits of vsize */
550  uint32_t vsize;
551  uint16_t asize;
552  uint16_t auxsize;
553  int ret;
554 
555  if (nsv->ahead[0].data || nsv->ahead[1].data)
556  return 0; //-1; /* hey! eat what you've in your plate first! */
557 
558 null_chunk_retry:
559  if (avio_feof(pb))
560  return -1;
561 
562  for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
563  err = nsv_resync(s);
564  if (err < 0)
565  return err;
566  if (nsv->state == NSV_FOUND_NSVS)
567  err = nsv_parse_NSVs_header(s);
568  if (err < 0)
569  return err;
570  if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
571  return -1;
572 
573  auxcount = avio_r8(pb);
574  vsize = avio_rl16(pb);
575  asize = avio_rl16(pb);
576  vsize = (vsize << 4) | (auxcount >> 4);
577  auxcount &= 0x0f;
578  av_log(s, AV_LOG_TRACE, "NSV CHUNK %d aux, %"PRIu32" bytes video, %d bytes audio\n", auxcount, vsize, asize);
579  /* skip aux stuff */
580  for (i = 0; i < auxcount; i++) {
581  uint32_t av_unused auxtag;
582  auxsize = avio_rl16(pb);
583  auxtag = avio_rl32(pb);
584  avio_skip(pb, auxsize);
585  vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming brain-dead */
586  }
587 
588  if (avio_feof(pb))
589  return -1;
590  if (!vsize && !asize) {
591  nsv->state = NSV_UNSYNC;
592  goto null_chunk_retry;
593  }
594 
595  /* map back streams to v,a */
596  if (s->nb_streams > 0)
597  st[s->streams[0]->id] = s->streams[0];
598  if (s->nb_streams > 1)
599  st[s->streams[1]->id] = s->streams[1];
600 
601  if (vsize && st[NSV_ST_VIDEO]) {
602  nst = st[NSV_ST_VIDEO]->priv_data;
603  pkt = &nsv->ahead[NSV_ST_VIDEO];
604  if ((ret = av_get_packet(pb, pkt, vsize)) < 0)
605  return ret;
606  pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;
607  pkt->dts = nst->frame_offset;
608  pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
609  for (i = 0; i < FFMIN(8, vsize); i++)
610  av_log(s, AV_LOG_TRACE, "NSV video: [%d] = %02x\n", i, pkt->data[i]);
611  }
612  if(st[NSV_ST_VIDEO])
613  ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
614 
615  if (asize && st[NSV_ST_AUDIO]) {
616  nst = st[NSV_ST_AUDIO]->priv_data;
617  pkt = &nsv->ahead[NSV_ST_AUDIO];
618  /* read raw audio specific header on the first audio chunk... */
619  /* on ALL audio chunks ?? seems so! */
620  if (asize && st[NSV_ST_AUDIO]->codecpar->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) {
621  uint8_t bps;
622  uint8_t channels;
623  uint16_t samplerate;
624  bps = avio_r8(pb);
625  channels = avio_r8(pb);
626  samplerate = avio_rl16(pb);
627  if (!channels || !samplerate)
628  return AVERROR_INVALIDDATA;
629  asize-=4;
630  av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
631  if (fill_header) {
632  ffstream(st[NSV_ST_AUDIO])->need_parsing = AVSTREAM_PARSE_NONE; /* we know everything */
633  if (bps != 16) {
634  av_log(s, AV_LOG_TRACE, "NSV AUDIO bit/sample != 16 (%d)!!!\n", bps);
635  }
636  bps /= channels; // ???
637  if (bps == 8)
639  samplerate /= 4;/* UGH ??? XXX */
640  channels = 1;
642  st[NSV_ST_AUDIO]->codecpar->sample_rate = samplerate;
643  av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
644  }
645  }
646  if ((ret = av_get_packet(pb, pkt, asize)) < 0)
647  return ret;
648  pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;
649  pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0; /* keyframe only likely on a sync frame */
650  if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
651  /* on a nsvs frame we have new information on a/v sync */
652  pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
653  pkt->dts *= (int64_t)1000 * nsv->framerate.den;
654  pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num;
655  av_log(s, AV_LOG_TRACE, "NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts);
656  }
657  nst->frame_offset++;
658  }
659 
660  nsv->state = NSV_UNSYNC;
661  return 0;
662 }
663 
664 
666 {
667  NSVContext *nsv = s->priv_data;
668  int i, err = 0;
669 
670  /* in case we don't already have something to eat ... */
671  if (!nsv->ahead[0].data && !nsv->ahead[1].data)
672  err = nsv_read_chunk(s, 0);
673  if (err < 0)
674  return err;
675 
676  /* now pick one of the plates */
677  for (i = 0; i < 2; i++) {
678  if (nsv->ahead[i].data) {
679  av_packet_move_ref(pkt, &nsv->ahead[i]);
680  return 0;
681  }
682  }
683 
684  /* this restaurant is not provisioned :^] */
685  return -1;
686 }
687 
688 static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
689 {
690  NSVContext *nsv = s->priv_data;
691  AVStream *st = s->streams[stream_index];
692  FFStream *const sti = ffstream(st);
693  NSVStream *nst = st->priv_data;
694  int index;
695 
696  index = av_index_search_timestamp(st, timestamp, flags);
697  if(index < 0)
698  return -1;
699 
700  if (avio_seek(s->pb, sti->index_entries[index].pos, SEEK_SET) < 0)
701  return -1;
702 
704  nsv->state = NSV_UNSYNC;
705  return 0;
706 }
707 
709 {
710  NSVContext *nsv = s->priv_data;
711 
712  av_freep(&nsv->nsvs_file_offset);
713  av_freep(&nsv->nsvs_timestamps);
714  if (nsv->ahead[0].data)
715  av_packet_unref(&nsv->ahead[0]);
716  if (nsv->ahead[1].data)
717  av_packet_unref(&nsv->ahead[1]);
718  return 0;
719 }
720 
721 static int nsv_probe(const AVProbeData *p)
722 {
723  int i, score = 0;
724 
725  /* check file header */
726  /* streamed files might not have any header */
727  if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
728  p->buf[2] == 'V' && (p->buf[3] == 'f' || p->buf[3] == 's'))
729  return AVPROBE_SCORE_MAX;
730  /* XXX: do streamed files always start at chunk boundary ?? */
731  /* or do we need to search NSVs in the byte stream ? */
732  /* seems the servers don't bother starting clean chunks... */
733  /* sometimes even the first header is at 9KB or something :^) */
734  for (i = 1; i < p->buf_size - 3; i++) {
735  if (AV_RL32(p->buf + i) == AV_RL32("NSVs")) {
736  /* Get the chunk size and check if at the end we are getting 0xBEEF */
737  int vsize = AV_RL24(p->buf+i+19) >> 4;
738  int asize = AV_RL16(p->buf+i+22);
739  int offset = i + 23 + asize + vsize + 1;
740  if (offset <= p->buf_size - 2 && AV_RL16(p->buf + offset) == 0xBEEF)
741  return 4*AVPROBE_SCORE_MAX/5;
742  score = AVPROBE_SCORE_MAX/5;
743  }
744  }
745  /* so we'll have more luck on extension... */
746  if (av_match_ext(p->filename, "nsv"))
748  /* FIXME: add mime-type check */
749  return score;
750 }
751 
753  .p.name = "nsv",
754  .p.long_name = NULL_IF_CONFIG_SMALL("Nullsoft Streaming Video"),
755  .priv_data_size = sizeof(NSVContext),
756  .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
762 };
nsv_read_chunk
static int nsv_read_chunk(AVFormatContext *s, int fill_header)
Definition: nsvdec.c:541
NSVContext::nsvs_timestamps
uint32_t * nsvs_timestamps
Definition: nsvdec.c:180
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:427
NSV_FOUND_NSVF
@ NSV_FOUND_NSVF
Definition: nsvdec.c:146
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:69
NSV_HAS_READ_NSVS
@ NSV_HAS_READ_NSVS
Definition: nsvdec.c:149
NSV_HAS_READ_NSVF
@ NSV_HAS_READ_NSVF
Definition: nsvdec.c:147
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
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
NSVContext::base_offset
int base_offset
Definition: nsvdec.c:168
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVStream::priv_data
void * priv_data
Definition: avformat.h:768
NSVContext::avsync
int16_t avsync
Definition: nsvdec.c:178
NSVStatus
NSVStatus
Definition: nsvdec.c:144
NSV_ST_VIDEO
#define NSV_ST_VIDEO
Definition: nsvdec.c:140
NSVStream
Definition: nsvdec.c:155
AV_CODEC_ID_RAWVIDEO
@ AV_CODEC_ID_RAWVIDEO
Definition: codec_id.h:65
av_unused
#define av_unused
Definition: attributes.h:131
AV_CODEC_ID_MPEG4
@ AV_CODEC_ID_MPEG4
Definition: codec_id.h:64
AVPacket::data
uint8_t * data
Definition: packet.h:520
AV_CODEC_ID_VP6
@ AV_CODEC_ID_VP6
Definition: codec_id.h:143
NSVStream::scale
int scale
Definition: nsvdec.c:158
NSVContext::NSVf_end
int NSVf_end
Definition: nsvdec.c:169
nsv_read_seek
static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: nsvdec.c:688
NSVStream::cum_len
int cum_len
Definition: nsvdec.c:164
AVCodecParameters::codec_tag
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:59
mathematics.h
AVProbeData::buf_size
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:454
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:575
sample_rate
sample_rate
Definition: ffmpeg_filter.c:424
NSVContext::vheight
uint16_t vheight
Definition: nsvdec.c:177
AVINDEX_KEYFRAME
#define AVINDEX_KEYFRAME
Definition: avformat.h:610
NSVContext
Definition: nsvdec.c:167
AVPROBE_SCORE_MAX
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:463
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:853
nsv_parse_NSVs_header
static int nsv_parse_NSVs_header(AVFormatContext *s)
Definition: nsvdec.c:376
T_NONE
#define T_NONE
Definition: nsvdec.c:131
AV_CODEC_ID_SPEEX
@ AV_CODEC_ID_SPEEX
Definition: codec_id.h:475
ffstream
static av_always_inline FFStream * ffstream(AVStream *st)
Definition: internal.h:417
fail
#define fail()
Definition: checkasm.h:185
read_seek
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition: libcdio.c:151
av_add_index_entry
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags)
Add an index entry into a sorted list.
Definition: seek.c:121
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
NSVContext::vwidth
uint16_t vwidth
Definition: nsvdec.c:177
AV_CODEC_ID_MP3
@ AV_CODEC_ID_MP3
preferred ID for decoding MPEG audio layer 1, 2 or 3
Definition: codec_id.h:441
AVStream::duration
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:802
avio_rl16
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:714
AVRational::num
int num
Numerator.
Definition: rational.h:59
nsv_read_header
static int nsv_read_header(AVFormatContext *s)
Definition: nsvdec.c:506
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:206
pkt
AVPacket * pkt
Definition: movenc.c:60
NSVContext::framerate
AVRational framerate
Definition: nsvdec.c:179
AVCodecTag
Definition: internal.h:42
duration
int64_t duration
Definition: movenc.c:65
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_read_callback.c:42
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
NSVStream::rate
int rate
Definition: nsvdec.c:159
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:553
AVProbeData::buf
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:453
NSV_GOT_AUDIO
@ NSV_GOT_AUDIO
Definition: nsvdec.c:152
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:134
AVProbeData::filename
const char * filename
Definition: avformat.h:452
av_match_ext
int av_match_ext(const char *filename, const char *extensions)
Return a positive value if the given filename has one of the given extensions, 0 otherwise.
Definition: format.c:41
AVIndexEntry::timestamp
int64_t timestamp
Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are...
Definition: avformat.h:604
channels
channels
Definition: aptx.h:31
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
NSV_FOUND_BEEF
@ NSV_FOUND_BEEF
Definition: nsvdec.c:150
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
FF_INFMT_FLAG_INIT_CLEANUP
#define FF_INFMT_FLAG_INIT_CLEANUP
For an FFInputFormat with this flag set read_close() needs to be called by the caller upon read_heade...
Definition: demux.h:35
FFStream::need_parsing
enum AVStreamParseType need_parsing
Definition: internal.h:386
AVFormatContext
Format I/O context.
Definition: avformat.h:1255
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:766
framerate
float framerate
Definition: av1_levels.c:29
NSVContext::duration
int64_t duration
Definition: nsvdec.c:175
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:550
NULL
#define NULL
Definition: coverity.c:32
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVSTREAM_PARSE_NONE
@ AVSTREAM_PARSE_NONE
Definition: avformat.h:592
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:451
NSVContext::ahead
AVPacket ahead[2]
Definition: nsvdec.c:173
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:180
av_packet_move_ref
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: packet.c:484
NSVStream::frame_offset
int frame_offset
Definition: nsvdec.c:156
index
int index
Definition: gxfenc.c:90
AVPROBE_SCORE_EXTENSION
#define AVPROBE_SCORE_EXTENSION
score for file extension
Definition: avformat.h:461
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:184
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:442
avio_rl32
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:730
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
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:94
ff_codec_get_id
enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
Definition: utils.c:133
AVChannelLayout
An AVChannelLayout holds information about the channel layout of audio data.
Definition: channel_layout.h:311
FFStream
Definition: internal.h:193
bps
unsigned bps
Definition: movenc.c:1852
size
int size
Definition: twinvq_data.h:10344
MKBETAG
#define MKBETAG(a, b, c, d)
Definition: macros.h:56
nsv_codec_video_tags
static const AVCodecTag nsv_codec_video_tags[]
Definition: nsvdec.c:184
AV_RL24
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_RL24
Definition: bytestream.h:93
nsv_read_packet
static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: nsvdec.c:665
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:41
nsv_probe
static int nsv_probe(const AVProbeData *p)
Definition: nsvdec.c:721
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:519
avio_r8
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:603
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
attributes.h
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:526
AV_CODEC_ID_VP5
@ AV_CODEC_ID_VP5
Definition: codec_id.h:142
AV_CODEC_ID_VP3
@ AV_CODEC_ID_VP3
Definition: codec_id.h:81
NSVContext::vtag
uint32_t vtag
Definition: nsvdec.c:176
nsv_resync
static int nsv_resync(AVFormatContext *s)
Definition: nsvdec.c:220
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AVCodecParameters::height
int height
Definition: codec_par.h:135
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
nsv_parse_NSVf_header
static int nsv_parse_NSVf_header(AVFormatContext *s)
Definition: nsvdec.c:261
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
demux.h
NSV_MAX_RESYNC
#define NSV_MAX_RESYNC
Definition: nsvdec.c:36
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:129
av_get_packet
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.
Definition: utils.c:91
AVStream::id
int id
Format-specific stream ID.
Definition: avformat.h:755
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:743
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:231
NSV_ST_AUDIO
#define NSV_ST_AUDIO
Definition: nsvdec.c:141
avformat.h
dict.h
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:749
NSV_GOT_VIDEO
@ NSV_GOT_VIDEO
Definition: nsvdec.c:151
AVRational::den
int den
Denominator.
Definition: rational.h:60
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:612
AVIndexEntry::pos
int64_t pos
Definition: avformat.h:603
AVPacket::stream_index
int stream_index
Definition: packet.h:522
avio_skip
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:318
FFStream::index_entries
AVIndexEntry * index_entries
Only used if the format does not support seeking natively.
Definition: internal.h:249
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
read_probe
static int read_probe(const AVProbeData *p)
Definition: cdg.c:30
AVCodecParameters::bits_per_coded_sample
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition: codec_par.h:110
mem.h
AV_CODEC_ID_PCM_U8
@ AV_CODEC_ID_PCM_U8
Definition: codec_id.h:333
NSV_FOUND_NSVS
@ NSV_FOUND_NSVS
Definition: nsvdec.c:148
AV_CHANNEL_LAYOUT_MONO
#define AV_CHANNEL_LAYOUT_MONO
Definition: channel_layout.h:386
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:497
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:88
FFInputFormat
Definition: demux.h:37
AVSTREAM_PARSE_FULL
@ AVSTREAM_PARSE_FULL
full parsing and repack
Definition: avformat.h:593
NSVContext::atag
uint32_t atag
Definition: nsvdec.c:176
AV_CODEC_ID_PCM_U16LE
@ AV_CODEC_ID_PCM_U16LE
Definition: codec_id.h:330
AV_CODEC_ID_VP8
@ AV_CODEC_ID_VP8
Definition: codec_id.h:192
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
TB_NSVF
#define TB_NSVF
Definition: nsvdec.c:136
NSVStream::start
int start
Definition: nsvdec.c:161
NSVContext::state
enum NSVStatus state
Definition: nsvdec.c:172
nsv_codec_audio_tags
static const AVCodecTag nsv_codec_audio_tags[]
Definition: nsvdec.c:205
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
NSVStream::new_frame_offset
int new_frame_offset
Definition: nsvdec.c:163
ff_nsv_demuxer
const FFInputFormat ff_nsv_demuxer
Definition: nsvdec.c:752
AVStream::start_time
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base.
Definition: avformat.h:792
NSVContext::nsvf
int nsvf
Definition: nsvdec.c:181
NSV_MAX_RESYNC_TRIES
#define NSV_MAX_RESYNC_TRIES
Definition: nsvdec.c:37
nsv_read_close
static int nsv_read_close(AVFormatContext *s)
Definition: nsvdec.c:708
NSVStream::sample_size
int sample_size
Definition: nsvdec.c:160
av_index_search_timestamp
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags)
Get the index for a specific timestamp.
Definition: seek.c:244
NSV_UNSYNC
@ NSV_UNSYNC
Definition: nsvdec.c:145
NSVContext::nsvs_file_offset
uint32_t * nsvs_file_offset
Definition: nsvdec.c:170
ff_alloc_extradata
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0.
Definition: utils.c:227
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:346
NSVContext::index_entries
int index_entries
Definition: nsvdec.c:171