1 /*
2  * Copyright © 2010 Mozilla Foundation
3  *
4  * This program is made available under an ISC-style license.  See the
5  * accompanying file LICENSE for details.
6  */
7 #if !defined(NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79)
8 #define NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79
9 
10 #include <limits.h>
11 #include <stdint.h>
12 
13 #if defined(__cplusplus)
14 extern "C" {
15 #endif
16 
17 /** @mainpage
18 
19     @section intro Introduction
20 
21     This is the documentation for the <tt>libnestegg</tt> C API.
22     <tt>libnestegg</tt> is a demultiplexing library for <a
23     href="http://www.webmproject.org/code/specs/container/">WebM</a>
24     media files.
25 
26     @section example Example code
27 
28     @code
29     nestegg * demux_ctx;
30     nestegg_init(&demux_ctx, io, NULL, -1);
31 
32     nestegg_packet * pkt;
33     while ((r = nestegg_read_packet(demux_ctx, &pkt)) > 0) {
34       unsigned int track;
35 
36       nestegg_packet_track(pkt, &track);
37 
38       // This example decodes the first track only.
39       if (track == 0) {
40         unsigned int chunk, chunks;
41 
42         nestegg_packet_count(pkt, &chunks);
43 
44         // Decode each chunk of data.
45         for (chunk = 0; chunk < chunks; ++chunk) {
46           unsigned char * data;
47           size_t data_size;
48 
49           nestegg_packet_data(pkt, chunk, &data, &data_size);
50 
51           example_codec_decode(codec_ctx, data, data_size);
52         }
53       }
54 
55       nestegg_free_packet(pkt);
56     }
57 
58     nestegg_destroy(demux_ctx);
59     @endcode
60 */
61 
62 
63 /** @file
64     The <tt>libnestegg</tt> C API. */
65 
66 #define NESTEGG_TRACK_VIDEO   0       /**< Track is of type video. */
67 #define NESTEGG_TRACK_AUDIO   1       /**< Track is of type audio. */
68 #define NESTEGG_TRACK_UNKNOWN INT_MAX /**< Track is of type unknown. */
69 
70 #define NESTEGG_CODEC_VP8     0       /**< Track uses Google On2 VP8 codec. */
71 #define NESTEGG_CODEC_VORBIS  1       /**< Track uses Xiph Vorbis codec. */
72 #define NESTEGG_CODEC_VP9     2       /**< Track uses Google On2 VP9 codec. */
73 #define NESTEGG_CODEC_OPUS    3       /**< Track uses Xiph Opus codec. */
74 #define NESTEGG_CODEC_AV1     4       /**< Track uses AOMedia AV1 codec. */
75 #define NESTEGG_CODEC_UNKNOWN INT_MAX /**< Track uses unknown codec. */
76 
77 #define NESTEGG_VIDEO_MONO              0 /**< Track is mono video. */
78 #define NESTEGG_VIDEO_STEREO_LEFT_RIGHT 1 /**< Track is side-by-side stereo video.  Left first. */
79 #define NESTEGG_VIDEO_STEREO_BOTTOM_TOP 2 /**< Track is top-bottom stereo video.  Right first. */
80 #define NESTEGG_VIDEO_STEREO_TOP_BOTTOM 3 /**< Track is top-bottom stereo video.  Left first. */
81 #define NESTEGG_VIDEO_STEREO_RIGHT_LEFT 11 /**< Track is side-by-side stereo video.  Right first. */
82 
83 #define NESTEGG_SEEK_SET 0 /**< Seek offset relative to beginning of stream. */
84 #define NESTEGG_SEEK_CUR 1 /**< Seek offset relative to current position in stream. */
85 #define NESTEGG_SEEK_END 2 /**< Seek offset relative to end of stream. */
86 
87 #define NESTEGG_LOG_DEBUG    1     /**< Debug level log message. */
88 #define NESTEGG_LOG_INFO     10    /**< Informational level log message. */
89 #define NESTEGG_LOG_WARNING  100   /**< Warning level log message. */
90 #define NESTEGG_LOG_ERROR    1000  /**< Error level log message. */
91 #define NESTEGG_LOG_CRITICAL 10000 /**< Critical level log message. */
92 
93 #define NESTEGG_ENCODING_COMPRESSION 0 /**< Content encoding type is compression. */
94 #define NESTEGG_ENCODING_ENCRYPTION  1 /**< Content encoding type is encryption. */
95 
96 #define NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE         0 /**< Packet does not have signal byte */
97 #define NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED   1 /**< Packet has signal byte and is unencrypted */
98 #define NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED     2 /**< Packet has signal byte and is encrypted */
99 #define NESTEGG_PACKET_HAS_SIGNAL_BYTE_PARTITIONED   4 /**< Packet has signal byte and is partitioned */
100 
101 #define NESTEGG_PACKET_HAS_KEYFRAME_FALSE   0 /**< Packet contains only keyframes. */
102 #define NESTEGG_PACKET_HAS_KEYFRAME_TRUE    1 /**< Packet does not contain any keyframes */
103 #define NESTEGG_PACKET_HAS_KEYFRAME_UNKNOWN 2 /**< Packet may or may not contain keyframes */
104 
105 typedef struct nestegg nestegg;               /**< Opaque handle referencing the stream state. */
106 typedef struct nestegg_packet nestegg_packet; /**< Opaque handle referencing a packet of data. */
107 
108 /** User supplied IO context. */
109 typedef struct {
110   /** User supplied read callback.
111       @param buffer   Buffer to read data into.
112       @param length   Length of supplied buffer in bytes.
113       @param userdata The #userdata supplied by the user.
114       @retval  1 Read succeeded.
115       @retval  0 End of stream.
116       @retval -1 Error. */
117   int (* read)(void * buffer, size_t length, void * userdata);
118 
119   /** User supplied seek callback.
120       @param offset   Offset within the stream to seek to.
121       @param whence   Seek direction.  One of #NESTEGG_SEEK_SET,
122                       #NESTEGG_SEEK_CUR, or #NESTEGG_SEEK_END.
123       @param userdata The #userdata supplied by the user.
124       @retval  0 Seek succeeded.
125       @retval -1 Error. */
126   int (* seek)(int64_t offset, int whence, void * userdata);
127 
128   /** User supplied tell callback.
129       @param userdata The #userdata supplied by the user.
130       @returns Current position within the stream.
131       @retval -1 Error. */
132   int64_t (* tell)(void * userdata);
133 
134   /** User supplied pointer to be passed to the IO callbacks. */
135   void * userdata;
136 } nestegg_io;
137 
138 /** Parameters specific to a video track. */
139 typedef struct {
140   unsigned int stereo_mode;    /**< Video mode.  One of #NESTEGG_VIDEO_MONO,
141                                     #NESTEGG_VIDEO_STEREO_LEFT_RIGHT,
142                                     #NESTEGG_VIDEO_STEREO_BOTTOM_TOP, or
143                                     #NESTEGG_VIDEO_STEREO_TOP_BOTTOM. */
144   unsigned int width;          /**< Width of the video frame in pixels. */
145   unsigned int height;         /**< Height of the video frame in pixels. */
146   unsigned int display_width;  /**< Display width of the video frame in pixels. */
147   unsigned int display_height; /**< Display height of the video frame in pixels. */
148   unsigned int crop_bottom;    /**< Pixels to crop from the bottom of the frame. */
149   unsigned int crop_top;       /**< Pixels to crop from the top of the frame. */
150   unsigned int crop_left;      /**< Pixels to crop from the left of the frame. */
151   unsigned int crop_right;     /**< Pixels to crop from the right of the frame. */
152   unsigned int alpha_mode;     /**< 1 if an additional opacity stream is available, otherwise 0. */
153   unsigned int matrix_coefficients;      /**< See Table 4 of ISO/IEC 23001-8:2016. */
154   unsigned int range;                    /**< Clipping of color ranges. */
155   unsigned int transfer_characteristics; /**< See Table 3 of ISO/IEC 23091-4. */
156   unsigned int primaries;                /**< See Table 2 of ISO/IEC 23091-4. */
157   double primary_r_chromacity_x;         /**< Red X chromaticity coordinate per CIE 1931.
158                                               NaN means element not present. */
159   double primary_r_chromacity_y;         /**< Red Y chromaticity coordinate per CIE 1931.
160                                               NaN means element not present. */
161   double primary_g_chromacity_x;         /**< Green X chromaticity coordinate per CIE 1931.
162                                               NaN means element not present. */
163   double primary_g_chromacity_y;         /**< Green Y chromaticity coordinate per CIE 1931.
164                                               NaN means element not present. */
165   double primary_b_chromacity_x;         /**< Blue X chromaticity coordinate per CIE 1931.
166                                               NaN means element not present. */
167   double primary_b_chromacity_y;         /**< Blue Y chromaticity coordinate per CIE 1931.
168                                               NaN means element not present. */
169   double white_point_chromaticity_x;     /**< White X chromaticity coordinate per CIE 1931.
170                                               NaN means element not present. */
171   double white_point_chromaticity_y;     /**< White Y chromaticity coordinate per CIE 1931.
172                                               NaN means element not present. */
173   double luminance_max;                  /**< Maximum luminance in cd/m2.
174                                               NaN means element not present. */
175   double luminance_min;                  /**< Minimum luminance in cd/m2.
176                                               NaN means element not present. */
177 } nestegg_video_params;
178 
179 /** Parameters specific to an audio track. */
180 typedef struct {
181   double rate;           /**< Sampling rate in Hz. */
182   unsigned int channels; /**< Number of audio channels. */
183   unsigned int depth;    /**< Bits per sample. */
184   uint64_t  codec_delay; /**< Nanoseconds that must be discarded from the start. */
185   uint64_t  seek_preroll;/**< Nanoseconds that must be discarded after a seek. */
186 } nestegg_audio_params;
187 
188 /** Logging callback function pointer. */
189 typedef void (* nestegg_log)(nestegg * context, unsigned int severity, char const * format, ...);
190 
191 /** Initialize a nestegg context.  During initialization the parser will
192     read forward in the stream processing all elements until the first
193     block of media is reached.  All track metadata has been processed at this point.
194     @param context  Storage for the new nestegg context.  @see nestegg_destroy
195     @param io       User supplied IO context.
196     @param callback Optional logging callback function pointer.  May be NULL.
197     @param max_offset Optional maximum offset to be read. Set -1 to ignore.
198     @retval  0 Success.
199     @retval -1 Error. */
200 int nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t max_offset);
201 
202 /** Destroy a nestegg context and free associated memory.
203     @param context #nestegg context to be freed.  @see nestegg_init */
204 void nestegg_destroy(nestegg * context);
205 
206 /** Query the duration of the media stream in nanoseconds.
207     @param context  Stream context initialized by #nestegg_init.
208     @param duration Storage for the queried duration.
209     @retval  0 Success.
210     @retval -1 Error. */
211 int nestegg_duration(nestegg * context, uint64_t * duration);
212 
213 /** Query the tstamp scale of the media stream in nanoseconds.
214     @note Timestamps presented by nestegg have been scaled by this value
215           before presentation to the caller.
216     @param context Stream context initialized by #nestegg_init.
217     @param scale   Storage for the queried scale factor.
218     @retval  0 Success.
219     @retval -1 Error. */
220 int nestegg_tstamp_scale(nestegg * context, uint64_t * scale);
221 
222 /** Query the number of tracks in the media stream.
223     @param context Stream context initialized by #nestegg_init.
224     @param tracks  Storage for the queried track count.
225     @retval  0 Success.
226     @retval -1 Error. */
227 int nestegg_track_count(nestegg * context, unsigned int * tracks);
228 
229 /** Query the start and end offset for a particular cluster.
230     @param context     Stream context initialized by #nestegg_init.
231     @param cluster_num Zero-based cluster number; order they appear in cues.
232     @param max_offset  Optional maximum offset to be read. Set -1 to ignore.
233     @param start_pos   Starting offset of the cluster. -1 means non-existant.
234     @param end_pos     Starting offset of the cluster. -1 means non-existant or
235                        final cluster.
236     @param tstamp      Starting timestamp of the cluster.
237     @retval  0 Success.
238     @retval -1 Error. */
239 int nestegg_get_cue_point(nestegg * context, unsigned int cluster_num,
240                           int64_t max_offset, int64_t * start_pos,
241                           int64_t * end_pos, uint64_t * tstamp);
242 
243 /** Seek to @a offset.  Stream will seek directly to offset.
244     Must be used to seek to the start of a cluster; the parser will not be
245     able to understand other offsets.
246     @param context Stream context initialized by #nestegg_init.
247     @param offset  Absolute offset in bytes.
248     @retval  0 Success.
249     @retval -1 Error. */
250 int nestegg_offset_seek(nestegg * context, uint64_t offset);
251 
252 /** Seek @a track to @a tstamp.  Stream seek will terminate at the earliest
253     key point in the stream at or before @a tstamp.  Other tracks in the
254     stream will output packets with unspecified but nearby timestamps.
255     @param context Stream context initialized by #nestegg_init.
256     @param track   Zero based track number.
257     @param tstamp  Absolute timestamp in nanoseconds.
258     @retval  0 Success.
259     @retval -1 Error. */
260 int nestegg_track_seek(nestegg * context, unsigned int track, uint64_t tstamp);
261 
262 /** Query the type specified by @a track.
263     @param context Stream context initialized by #nestegg_init.
264     @param track   Zero based track number.
265     @retval #NESTEGG_TRACK_VIDEO   Track type is video.
266     @retval #NESTEGG_TRACK_AUDIO   Track type is audio.
267     @retval #NESTEGG_TRACK_UNKNOWN Track type is unknown.
268     @retval -1 Error. */
269 int nestegg_track_type(nestegg * context, unsigned int track);
270 
271 /** Query the codec ID specified by @a track.
272     @param context Stream context initialized by #nestegg_init.
273     @param track   Zero based track number.
274     @retval #NESTEGG_CODEC_VP8     Track codec is VP8.
275     @retval #NESTEGG_CODEC_VP9     Track codec is VP9.
276     @retval #NESTEGG_CODEC_AV1     Track codec is AV1.
277     @retval #NESTEGG_CODEC_VORBIS  Track codec is Vorbis.
278     @retval #NESTEGG_CODEC_OPUS    Track codec is Opus.
279     @retval #NESTEGG_CODEC_UNKNOWN Track codec is unknown.
280     @retval -1 Error. */
281 int nestegg_track_codec_id(nestegg * context, unsigned int track);
282 
283 /** Query the number of codec initialization chunks for @a track.  Each
284     chunk of data should be passed to the codec initialization functions in
285     the order returned.
286     @param context Stream context initialized by #nestegg_init.
287     @param track   Zero based track number.
288     @param count   Storage for the queried chunk count.
289     @retval  0 Success.
290     @retval -1 Error. */
291 int nestegg_track_codec_data_count(nestegg * context, unsigned int track,
292                                    unsigned int * count);
293 
294 /** Get a pointer to chunk number @a item of codec initialization data for
295     @a track.
296     @param context Stream context initialized by #nestegg_init.
297     @param track   Zero based track number.
298     @param item    Zero based chunk item number.
299     @param data    Storage for the queried data pointer.
300                    The data is owned by the #nestegg context.
301     @param length  Storage for the queried data size.
302     @retval  0 Success.
303     @retval -1 Error. */
304 int nestegg_track_codec_data(nestegg * context, unsigned int track, unsigned int item,
305                              unsigned char ** data, size_t * length);
306 
307 /** Query the video parameters specified by @a track.
308     @param context Stream context initialized by #nestegg_init.
309     @param track   Zero based track number.
310     @param params  Storage for the queried video parameters.
311     @retval  0 Success.
312     @retval -1 Error. */
313 int nestegg_track_video_params(nestegg * context, unsigned int track,
314                                nestegg_video_params * params);
315 
316 /** Query the audio parameters specified by @a track.
317     @param context Stream context initialized by #nestegg_init.
318     @param track   Zero based track number.
319     @param params  Storage for the queried audio parameters.
320     @retval  0 Success.
321     @retval -1 Error. */
322 int nestegg_track_audio_params(nestegg * context, unsigned int track,
323                                nestegg_audio_params * params);
324 
325 /** Query the encoding status for @a track. If a track has multiple encodings
326     the first will be returned.
327     @param context Stream context initialized by #nestegg_init.
328     @param track   Zero based track number.
329     @retval #NESTEGG_ENCODING_COMPRESSION The track is compressed, but not encrypted.
330     @retval #NESTEGG_ENCODING_ENCRYPTION The track is encrypted and compressed.
331     @retval -1 Error. */
332 int nestegg_track_encoding(nestegg * context, unsigned int track);
333 
334 /** Query the ContentEncKeyId for @a track. Will return an error if the track
335     in not encrypted, or is not recognized.
336     @param context                   Stream context initialized by #nestegg_init.
337     @param track                     Zero based track number.
338     @param content_enc_key_id        Storage for queried id. The content encryption key used.
339                                      Owned by nestegg and will be freed separately.
340     @param content_enc_key_id_length Length of the queried ContentEncKeyId in bytes.
341     @retval  0 Success.
342     @retval -1 Error. */
343 int nestegg_track_content_enc_key_id(nestegg * context, unsigned int track,
344                                      unsigned char const ** content_enc_key_id,
345                                      size_t * content_enc_key_id_length);
346 
347 /** Query the default frame duration for @a track.  For a video track, this
348     is typically the inverse of the video frame rate.
349     @param context  Stream context initialized by #nestegg_init.
350     @param track    Zero based track number.
351     @param duration Storage for the default duration in nanoseconds.
352     @retval  0 Success.
353     @retval -1 Error. */
354 int nestegg_track_default_duration(nestegg * context, unsigned int track,
355                                    uint64_t * duration);
356 
357 /** Reset parser state to the last valid state before nestegg_read_packet failed.
358     @param context Stream context initialized by #nestegg_init.
359     @retval  0 Success.
360     @retval -1 Error. */
361 int nestegg_read_reset(nestegg * context);
362 
363 /** Read a packet of media data.  A packet consists of one or more chunks of
364     data associated with a single track.  nestegg_read_packet should be
365     called in a loop while the return value is 1 to drive the stream parser
366     forward.  @see nestegg_free_packet
367     @param context Context returned by #nestegg_init.
368     @param packet  Storage for the returned nestegg_packet.
369     @retval  1 Additional packets may be read in subsequent calls.
370     @retval  0 End of stream.
371     @retval -1 Error. */
372 int nestegg_read_packet(nestegg * context, nestegg_packet ** packet);
373 
374 /** Destroy a nestegg_packet and free associated memory.
375     @param packet #nestegg_packet to be freed. @see nestegg_read_packet */
376 void nestegg_free_packet(nestegg_packet * packet);
377 
378 /** Query the keyframe status for a given packet.
379     @param packet Packet initialized by #nestegg_read_packet.
380     @retval #NESTEGG_PACKET_HAS_KEYFRAME_FALSE   Packet contains no keyframes.
381     @retval #NESTEGG_PACKET_HAS_KEYFRAME_TRUE    Packet contains keyframes.
382     @retval #NESTEGG_PACKET_HAS_KEYFRAME_UNKNOWN Unknown packet keyframe content.
383     @retval -1 Error. */
384 int nestegg_packet_has_keyframe(nestegg_packet * packet);
385 
386 /** Query the track number of @a packet.
387     @param packet Packet initialized by #nestegg_read_packet.
388     @param track  Storage for the queried zero based track index.
389     @retval  0 Success.
390     @retval -1 Error. */
391 int nestegg_packet_track(nestegg_packet * packet, unsigned int * track);
392 
393 /** Query the timestamp in nanoseconds of @a packet.
394     @param packet Packet initialized by #nestegg_read_packet.
395     @param tstamp Storage for the queried timestamp in nanoseconds.
396     @retval  0 Success.
397     @retval -1 Error. */
398 int nestegg_packet_tstamp(nestegg_packet * packet, uint64_t * tstamp);
399 
400 /** Query the duration in nanoseconds of @a packet.
401     @param packet Packet initialized by #nestegg_read_packet.
402     @param duration Storage for the queried duration in nanoseconds.
403     @retval  0 Success.
404     @retval -1 Error. */
405 int nestegg_packet_duration(nestegg_packet * packet, uint64_t * duration);
406 
407 /** Query the number of data chunks contained in @a packet.
408     @param packet Packet initialized by #nestegg_read_packet.
409     @param count  Storage for the queried chunk count.
410     @retval  0 Success.
411     @retval -1 Error. */
412 int nestegg_packet_count(nestegg_packet * packet, unsigned int * count);
413 
414 /** Get a pointer to chunk number @a item of packet data.
415     @param packet  Packet initialized by #nestegg_read_packet.
416     @param item    Zero based chunk item number.
417     @param data    Storage for the queried data pointer.
418                    The data is owned by the #nestegg_packet packet.
419     @param length  Storage for the queried data size.
420     @retval  0 Success.
421     @retval -1 Error. */
422 int nestegg_packet_data(nestegg_packet * packet, unsigned int item,
423                         unsigned char ** data, size_t * length);
424 
425 /** Get a pointer to additional data with identifier @a id of additional packet
426     data. If @a id isn't present in the packet, returns -1.
427     @param packet  Packet initialized by #nestegg_read_packet.
428     @param id      Codec specific identifer. For VP8, use 1 to get a VP8 encoded
429                    frame containing an alpha channel in its Y plane.
430     @param data    Storage for the queried data pointer.
431                    The data is owned by the #nestegg_packet packet.
432     @param length  Storage for the queried data size.
433     @retval  0 Success.
434     @retval -1 Error. */
435 int nestegg_packet_additional_data(nestegg_packet * packet, unsigned int id,
436                                    unsigned char ** data, size_t * length);
437 
438 /** Returns discard_padding for given packet
439     @param packet  Packet initialized by #nestegg_read_packet.
440     @param discard_padding pointer to store discard padding in.
441     @retval  0 Success.
442     @retval -1 Error. */
443 int nestegg_packet_discard_padding(nestegg_packet * packet,
444                                    int64_t * discard_padding);
445 
446 /** Query if a packet is encrypted.
447     @param packet Packet initialized by #nestegg_read_packet.
448     @retval  #NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE No signal byte, encryption
449              information not read from packet.
450     @retval  #NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED Encrypted bit not
451              set, encryption information not read from packet.
452     @retval  #NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED Encrypted bit set,
453              encryption infomation read from packet.
454     @retval  #NESTEGG_PACKET_HAS_SIGNAL_BYTE_PARTITIONED Partitioned bit set,
455              encryption and parition information read from packet.
456     @retval -1 Error.*/
457 int nestegg_packet_encryption(nestegg_packet * packet);
458 
459 /** Query the IV for an encrypted packet. Expects a packet from an encrypted
460     track, and will return error if given a packet that has no signal btye.
461     @param packet Packet initialized by #nestegg_read_packet.
462     @param iv     Storage for queried iv.
463     @param length Length of returned iv, may be 0.
464                   The data is owned by the #nestegg_packet packet.
465     @retval  0 Success.
466     @retval -1 Error.
467   */
468 int nestegg_packet_iv(nestegg_packet * packet, unsigned char const ** iv,
469                       size_t * length);
470 
471 /** Query the packet for offsets.
472 @param packet            Packet initialized by #nestegg_read_packet.
473 @param partition_offsets Storage for queried offsets.
474 @param num_offsets       Length of returned offsets, may be 0.
475 The data is owned by the #nestegg_packet packet.
476 @retval  0 Success.
477 @retval -1 Error.
478 */
479 int nestegg_packet_offsets(nestegg_packet * packet,
480                            uint32_t const ** partition_offsets,
481                            uint8_t * num_offsets);
482 
483 /** Returns reference_block given packet
484     @param packet          Packet initialized by #nestegg_read_packet.
485     @param reference_block pointer to store reference block in.
486     @retval  0 Success.
487     @retval -1 Error. */
488 int nestegg_packet_reference_block(nestegg_packet * packet,
489                                    int64_t * reference_block);
490 
491 /** Query the presence of cues.
492     @param context  Stream context initialized by #nestegg_init.
493     @retval 0 The media has no cues.
494     @retval 1 The media has cues. */
495 int nestegg_has_cues(nestegg * context);
496 
497 /** Try to determine if the buffer looks like the beginning of a WebM file.
498     @param buffer A buffer containing the beginning of a media file.
499     @param length The size of the buffer.
500     @retval 0 The file is not a WebM file.
501     @retval 1 The file is a WebM file. */
502 int nestegg_sniff(unsigned char const * buffer, size_t length);
503 
504 #if defined(__cplusplus)
505 }
506 #endif
507 
508 #endif /* NESTEGG_671cac2a_365d_ed69_d7a3_4491d3538d79 */
509