• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <assert.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include "nestegg/nestegg.h"
13 
14 #undef DEBUG
15 #define SEEK_TEST
16 
17 static int
stdio_read(void * p,size_t length,void * fp)18 stdio_read(void * p, size_t length, void * fp)
19 {
20   size_t r;
21 
22   r = fread(p, length, 1, fp);
23   if (r == 0 && feof(fp))
24     return 0;
25   return r == 0 ? -1 : 1;
26 }
27 
28 static int
stdio_seek(int64_t offset,int whence,void * fp)29 stdio_seek(int64_t offset, int whence, void * fp)
30 {
31   return fseek(fp, offset, whence);
32 }
33 
34 static int64_t
stdio_tell(void * fp)35 stdio_tell(void * fp)
36 {
37   return ftell(fp);
38 }
39 
40 static void
log_callback(nestegg * ctx,unsigned int severity,char const * fmt,...)41 log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
42 {
43   va_list ap;
44   char const * sev = NULL;
45 
46 #ifndef DEBUG
47   if (severity < NESTEGG_LOG_WARNING)
48     return;
49 #endif
50 
51   switch (severity) {
52   case NESTEGG_LOG_DEBUG:
53     sev = "debug:   ";
54     break;
55   case NESTEGG_LOG_WARNING:
56     sev = "warning: ";
57     break;
58   case NESTEGG_LOG_CRITICAL:
59     sev = "critical:";
60     break;
61   default:
62     sev = "unknown: ";
63   }
64 
65   fprintf(stderr, "%p %s ", (void *) ctx, sev);
66 
67   va_start(ap, fmt);
68   vfprintf(stderr, fmt, ap);
69   va_end(ap);
70 
71   fprintf(stderr, "\n");
72 }
73 
74 int
main(int argc,char * argv[])75 main(int argc, char * argv[])
76 {
77   FILE * fp;
78   int r, type;
79   nestegg * ctx;
80   nestegg_audio_params aparams;
81   nestegg_packet * pkt;
82   nestegg_video_params vparams;
83   size_t length, size;
84   uint64_t duration, tstamp, pkt_tstamp;
85   unsigned char * codec_data, * ptr;
86   unsigned int cnt, i, j, track, tracks, pkt_cnt, pkt_track;
87   unsigned int data_items = 0;
88   nestegg_io io = {
89     stdio_read,
90     stdio_seek,
91     stdio_tell,
92     NULL
93   };
94 
95   if (argc != 2)
96     return EXIT_FAILURE;
97 
98   fp = fopen(argv[1], "rb");
99   if (!fp)
100     return EXIT_FAILURE;
101 
102   io.userdata = fp;
103 
104   ctx = NULL;
105   r = nestegg_init(&ctx, io, log_callback);
106   if (r != 0)
107     return EXIT_FAILURE;
108 
109   nestegg_track_count(ctx, &tracks);
110   nestegg_duration(ctx, &duration);
111 #ifdef DEBUG
112   fprintf(stderr, "media has %u tracks and duration %fs\n", tracks, duration / 1e9);
113 #endif
114 
115   for (i = 0; i < tracks; ++i) {
116     type = nestegg_track_type(ctx, i);
117 #ifdef DEBUG
118     fprintf(stderr, "track %u: type: %d codec: %d", i,
119             type, nestegg_track_codec_id(ctx, i));
120 #endif
121     nestegg_track_codec_data_count(ctx, i, &data_items);
122     for (j = 0; j < data_items; ++j) {
123       nestegg_track_codec_data(ctx, i, j, &codec_data, &length);
124 #ifdef DEBUG
125       fprintf(stderr, " (%p, %u)", codec_data, (unsigned int) length);
126 #endif
127     }
128     if (type == NESTEGG_TRACK_VIDEO) {
129       nestegg_track_video_params(ctx, i, &vparams);
130 #ifdef DEBUG
131       fprintf(stderr, " video: %ux%u (d: %ux%u %ux%ux%ux%u)",
132               vparams.width, vparams.height,
133               vparams.display_width, vparams.display_height,
134               vparams.crop_top, vparams.crop_left, vparams.crop_bottom, vparams.crop_right);
135 #endif
136     } else if (type == NESTEGG_TRACK_AUDIO) {
137       nestegg_track_audio_params(ctx, i, &aparams);
138 #ifdef DEBUG
139       fprintf(stderr, " audio: %.2fhz %u bit %u channels",
140               aparams.rate, aparams.depth, aparams.channels);
141 #endif
142     }
143 #ifdef DEBUG
144     fprintf(stderr, "\n");
145 #endif
146   }
147 
148 #ifdef SEEK_TEST
149 #ifdef DEBUG
150   fprintf(stderr, "seek to middle\n");
151 #endif
152   r = nestegg_track_seek(ctx, 0, duration / 2);
153   if (r == 0) {
154 #ifdef DEBUG
155     fprintf(stderr, "middle ");
156 #endif
157     r = nestegg_read_packet(ctx, &pkt);
158     if (r == 1) {
159       nestegg_packet_track(pkt, &track);
160       nestegg_packet_count(pkt, &cnt);
161       nestegg_packet_tstamp(pkt, &tstamp);
162 #ifdef DEBUG
163       fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
164 #endif
165       nestegg_free_packet(pkt);
166     } else {
167 #ifdef DEBUG
168       fprintf(stderr, "middle seek failed\n");
169 #endif
170     }
171   }
172 
173 #ifdef DEBUG
174   fprintf(stderr, "seek to ~end\n");
175 #endif
176   r = nestegg_track_seek(ctx, 0, duration - (duration / 10));
177   if (r == 0) {
178 #ifdef DEBUG
179     fprintf(stderr, "end ");
180 #endif
181     r = nestegg_read_packet(ctx, &pkt);
182     if (r == 1) {
183       nestegg_packet_track(pkt, &track);
184       nestegg_packet_count(pkt, &cnt);
185       nestegg_packet_tstamp(pkt, &tstamp);
186 #ifdef DEBUG
187       fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
188 #endif
189       nestegg_free_packet(pkt);
190     } else {
191 #ifdef DEBUG
192       fprintf(stderr, "end seek failed\n");
193 #endif
194     }
195   }
196 
197 #ifdef DEBUG
198   fprintf(stderr, "seek to ~start\n");
199 #endif
200   r = nestegg_track_seek(ctx, 0, duration / 10);
201   if (r == 0) {
202 #ifdef DEBUG
203     fprintf(stderr, "start ");
204 #endif
205     r = nestegg_read_packet(ctx, &pkt);
206     if (r == 1) {
207       nestegg_packet_track(pkt, &track);
208       nestegg_packet_count(pkt, &cnt);
209       nestegg_packet_tstamp(pkt, &tstamp);
210 #ifdef DEBUG
211       fprintf(stderr, "* t %u pts %f frames %u\n", track, tstamp / 1e9, cnt);
212 #endif
213       nestegg_free_packet(pkt);
214     } else {
215 #ifdef DEBUG
216       fprintf(stderr, "start seek failed\n");
217 #endif
218     }
219   }
220 #endif
221 
222   while (nestegg_read_packet(ctx, &pkt) > 0) {
223     nestegg_packet_track(pkt, &pkt_track);
224     nestegg_packet_count(pkt, &pkt_cnt);
225     nestegg_packet_tstamp(pkt, &pkt_tstamp);
226 
227 #ifdef DEBUG
228     fprintf(stderr, "t %u pts %f frames %u: ", pkt_track, pkt_tstamp / 1e9, pkt_cnt);
229 #endif
230 
231     for (i = 0; i < pkt_cnt; ++i) {
232       nestegg_packet_data(pkt, i, &ptr, &size);
233 #ifdef DEBUG
234       fprintf(stderr, "%u ", (unsigned int) size);
235 #endif
236     }
237 #ifdef DEBUG
238     fprintf(stderr, "\n");
239 #endif
240 
241     nestegg_free_packet(pkt);
242   }
243 
244   nestegg_destroy(ctx);
245   fclose(fp);
246 
247   return EXIT_SUCCESS;
248 }
249