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