Merge "Modified the inverse walsh to output directly"
[profile/ivi/libvpx.git] / vp8_scalable_patterns.c
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11
12 /*
13  * This is an example demonstrating how to implement a multi-layer VP8
14  * encoding scheme based on temporal scalability for video applications
15  * that benefit from a scalable bitstream.
16  */
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #define VPX_CODEC_DISABLE_COMPAT 1
22 #include "vpx/vpx_encoder.h"
23 #include "vpx/vp8cx.h"
24 #define interface (vpx_codec_vp8_cx())
25 #define fourcc    0x30385056
26
27 #define IVF_FILE_HDR_SZ  (32)
28 #define IVF_FRAME_HDR_SZ (12)
29
30 static void mem_put_le16(char *mem, unsigned int val) {
31     mem[0] = val;
32     mem[1] = val>>8;
33 }
34
35 static void mem_put_le32(char *mem, unsigned int val) {
36     mem[0] = val;
37     mem[1] = val>>8;
38     mem[2] = val>>16;
39     mem[3] = val>>24;
40 }
41
42 static void die(const char *fmt, ...) {
43     va_list ap;
44
45     va_start(ap, fmt);
46     vprintf(fmt, ap);
47     if(fmt[strlen(fmt)-1] != '\n')
48         printf("\n");
49     exit(EXIT_FAILURE);
50 }
51
52 static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
53     const char *detail = vpx_codec_error_detail(ctx);
54
55     printf("%s: %s\n", s, vpx_codec_error(ctx));
56     if(detail)
57         printf("    %s\n",detail);
58     exit(EXIT_FAILURE);
59 }
60
61 static int read_frame(FILE *f, vpx_image_t *img) {
62     size_t nbytes, to_read;
63     int    res = 1;
64
65     to_read = img->w*img->h*3/2;
66     nbytes = fread(img->planes[0], 1, to_read, f);
67     if(nbytes != to_read) {
68         res = 0;
69         if(nbytes > 0)
70             printf("Warning: Read partial frame. Check your width & height!\n");
71     }
72     return res;
73 }
74
75 static void write_ivf_file_header(FILE *outfile,
76                                   const vpx_codec_enc_cfg_t *cfg,
77                                   int frame_cnt) {
78     char header[32];
79
80     if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
81         return;
82     header[0] = 'D';
83     header[1] = 'K';
84     header[2] = 'I';
85     header[3] = 'F';
86     mem_put_le16(header+4,  0);                   /* version */
87     mem_put_le16(header+6,  32);                  /* headersize */
88     mem_put_le32(header+8,  fourcc);              /* headersize */
89     mem_put_le16(header+12, cfg->g_w);            /* width */
90     mem_put_le16(header+14, cfg->g_h);            /* height */
91     mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
92     mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
93     mem_put_le32(header+24, frame_cnt);           /* length */
94     mem_put_le32(header+28, 0);                   /* unused */
95
96     if(fwrite(header, 1, 32, outfile));
97 }
98
99
100 static void write_ivf_frame_header(FILE *outfile,
101                                    const vpx_codec_cx_pkt_t *pkt)
102 {
103     char             header[12];
104     vpx_codec_pts_t  pts;
105
106     if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
107         return;
108
109     pts = pkt->data.frame.pts;
110     mem_put_le32(header, pkt->data.frame.sz);
111     mem_put_le32(header+4, pts&0xFFFFFFFF);
112     mem_put_le32(header+8, pts >> 32);
113
114     if(fwrite(header, 1, 12, outfile));
115 }
116
117 static int mode_to_num_layers[7] = {2, 2, 3, 3, 3, 3, 5};
118
119 int main(int argc, char **argv) {
120     FILE                *infile, *outfile[MAX_LAYERS];
121     vpx_codec_ctx_t      codec;
122     vpx_codec_enc_cfg_t  cfg;
123     int                  frame_cnt = 0;
124     vpx_image_t          raw;
125     vpx_codec_err_t      res;
126     unsigned int         width;
127     unsigned int         height;
128     int                  frame_avail;
129     int                  got_data;
130     int                  flags = 0;
131     int                  i;
132
133     int                  layering_mode = 0;
134     int                  frames_in_layer[MAX_LAYERS] = {0};
135     int                  layer_flags[MAX_PERIODICITY] = {0};
136
137     // Check usage and arguments
138     if (argc < 7)
139         die("Usage: %s <infile> <outfile> <width> <height> <mode> "
140             "<Rate_0> ... <Rate_nlayers-1>\n", argv[0]);
141
142     width  = strtol (argv[3], NULL, 0);
143     height = strtol (argv[4], NULL, 0);
144     if (width < 16 || width%2 || height <16 || height%2)
145         die ("Invalid resolution: %d x %d", width, height);
146
147     if (!sscanf(argv[5], "%d", &layering_mode))
148         die ("Invalid mode %s", argv[5]);
149     if (layering_mode<0 || layering_mode>6)
150         die ("Invalid mode (0..6) %s", argv[5]);
151
152     if (argc != 6+mode_to_num_layers[layering_mode])
153         die ("Invalid number of arguments");
154
155     if (!vpx_img_alloc (&raw, VPX_IMG_FMT_I420, width, height, 1))
156         die ("Failed to allocate image", width, height);
157
158     printf("Using %s\n",vpx_codec_iface_name(interface));
159
160     // Populate encoder configuration
161     res = vpx_codec_enc_config_default(interface, &cfg, 0);
162     if(res) {
163         printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
164         return EXIT_FAILURE;
165     }
166
167     // Update the default configuration with our settings
168     cfg.g_w = width;
169     cfg.g_h = height;
170
171     for (i=6; i<6+mode_to_num_layers[layering_mode]; i++)
172         if (!sscanf(argv[i], "%d", &cfg.ts_target_bitrate[i-6]))
173             die ("Invalid data rate %s", argv[i]);
174
175     // Real time parameters
176     cfg.rc_dropframe_thresh = 0;
177     cfg.rc_end_usage        = VPX_CBR;
178     cfg.rc_resize_allowed   = 0;
179     cfg.rc_min_quantizer    = 4;
180     cfg.rc_max_quantizer    = 63;
181     cfg.rc_undershoot_pct   = 98;
182     cfg.rc_overshoot_pct    = 100;
183     cfg.rc_buf_initial_sz   = 500;
184     cfg.rc_buf_optimal_sz   = 600;
185     cfg.rc_buf_sz           = 1000;
186
187     // Enable error resilient mode
188     cfg.g_error_resilient = 1;
189     cfg.g_lag_in_frames   = 0;
190     cfg.kf_mode           = VPX_KF_DISABLED;
191
192     // Disable automatic keyframe placement
193     cfg.kf_min_dist = cfg.kf_max_dist = 1000;
194
195     // Temporal scaling parameters:
196     // NOTE: The 3 prediction frames cannot be used interchangebly due to
197     // differences in the way they are handled throughout the code. The
198     // frames should be allocated to layers in the order LAST, GF, ARF.
199     // Other combinations work, but may produce slightly inferior results.
200     switch (layering_mode)
201     {
202
203     case 0:
204     {
205         // 2-layers, 2-frame period
206         int ids[2] = {0,1};
207         cfg.ts_number_layers     = 2;
208         cfg.ts_periodicity       = 2;
209         cfg.ts_rate_decimator[0] = 2;
210         cfg.ts_rate_decimator[1] = 1;
211         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
212
213         // 0=L, 1=GF, Intra-layer prediction enabled
214         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
215                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
216                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
217         layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
218                          VP8_EFLAG_NO_REF_ARF;
219 #if 0
220         // 0=L, 1=GF, Intra-layer 1 prediction disabled
221         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
222                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
223                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
224         layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
225                          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
226 #endif
227         break;
228     }
229
230     case 1:
231     {
232         // 2-layers, 3-frame period
233         int ids[3] = {0,1,1};
234         cfg.ts_number_layers     = 2;
235         cfg.ts_periodicity       = 3;
236         cfg.ts_rate_decimator[0] = 3;
237         cfg.ts_rate_decimator[1] = 1;
238         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
239
240         // 0=L, 1=GF, Intra-layer prediction enabled
241         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
242                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
243                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
244         layer_flags[1] =
245         layer_flags[2] = VP8_EFLAG_NO_REF_GF  |
246                          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
247                                                 VP8_EFLAG_NO_UPD_LAST;
248         break;
249     }
250
251     case 2:
252     {
253         // 3-layers, 6-frame period
254         int ids[6] = {0,2,2,1,2,2};
255         cfg.ts_number_layers     = 3;
256         cfg.ts_periodicity       = 6;
257         cfg.ts_rate_decimator[0] = 6;
258         cfg.ts_rate_decimator[1] = 3;
259         cfg.ts_rate_decimator[2] = 1;
260         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
261
262         // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled
263         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
264                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
265                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
266         layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
267                                                 VP8_EFLAG_NO_UPD_LAST;
268         layer_flags[1] =
269         layer_flags[2] =
270         layer_flags[4] =
271         layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
272         break;
273     }
274
275     case 3:
276     {
277         // 3-layers, 4-frame period
278         int ids[6] = {0,2,1,2};
279         cfg.ts_number_layers     = 3;
280         cfg.ts_periodicity       = 4;
281         cfg.ts_rate_decimator[0] = 4;
282         cfg.ts_rate_decimator[1] = 2;
283         cfg.ts_rate_decimator[2] = 1;
284         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
285
286         // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled
287         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
288                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
289                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
290         layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
291                          VP8_EFLAG_NO_UPD_ARF |
292                          VP8_EFLAG_NO_UPD_LAST;
293         layer_flags[1] =
294         layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
295                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
296                          VP8_EFLAG_NO_UPD_ARF;
297         break;
298         cfg.ts_rate_decimator[2] = 1;
299     }
300
301     case 4:
302     {
303         // 3-layers, 4-frame period
304         int ids[6] = {0,2,1,2};
305         cfg.ts_number_layers     = 3;
306         cfg.ts_periodicity       = 4;
307         cfg.ts_rate_decimator[0] = 4;
308         cfg.ts_rate_decimator[1] = 2;
309         cfg.ts_rate_decimator[2] = 1;
310         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
311
312         // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1,
313         // disabled in layer 2
314         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
315                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
316                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
317         layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
318                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
319         layer_flags[1] =
320         layer_flags[3] = VP8_EFLAG_NO_REF_ARF |
321                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
322                          VP8_EFLAG_NO_UPD_ARF;
323         break;
324     }
325
326     case 5:
327     {
328         // 3-layers, 4-frame period
329         int ids[6] = {0,2,1,2};
330         cfg.ts_number_layers     = 3;
331         cfg.ts_periodicity       = 4;
332         cfg.ts_rate_decimator[0] = 4;
333         cfg.ts_rate_decimator[1] = 2;
334         cfg.ts_rate_decimator[2] = 1;
335         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
336
337         // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled
338         layer_flags[0] = VPX_EFLAG_FORCE_KF  |
339                          VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
340                          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
341         layer_flags[2] = VP8_EFLAG_NO_REF_ARF |
342                          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
343         layer_flags[1] =
344         layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
345         break;
346     }
347
348     case 6:
349     {
350         // NOTE: Probably of academic interest only
351
352         // 5-layers, 16-frame period
353         int ids[16] = {0,4,3,4,2,4,3,4,1,4,3,4,2,4,3,4};
354         cfg.ts_number_layers     = 5;
355         cfg.ts_periodicity       = 16;
356         cfg.ts_rate_decimator[0] = 16;
357         cfg.ts_rate_decimator[1] = 8;
358         cfg.ts_rate_decimator[2] = 4;
359         cfg.ts_rate_decimator[3] = 2;
360         cfg.ts_rate_decimator[4] = 1;
361         memcpy(cfg.ts_layer_id, ids, sizeof(ids));
362
363         layer_flags[0]  = VPX_EFLAG_FORCE_KF;
364         layer_flags[1]  =
365         layer_flags[3]  =
366         layer_flags[5]  =
367         layer_flags[7]  =
368         layer_flags[9]  =
369         layer_flags[11] =
370         layer_flags[13] =
371         layer_flags[15] = VP8_EFLAG_NO_UPD_LAST |
372                           VP8_EFLAG_NO_UPD_GF   |
373                           VP8_EFLAG_NO_UPD_ARF  |
374                           VP8_EFLAG_NO_UPD_ENTROPY;
375         layer_flags[2]  =
376         layer_flags[6]  =
377         layer_flags[10] =
378         layer_flags[14] = 0;
379         layer_flags[4]  =
380         layer_flags[12] = VP8_EFLAG_NO_REF_LAST;
381         layer_flags[8]  = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF |
382                           VP8_EFLAG_NO_UPD_ENTROPY;
383         break;
384     }
385
386     default:
387         break;
388     }
389
390     // Open input file
391     if(!(infile = fopen(argv[1], "rb")))
392         die("Failed to open %s for reading", argv[1]);
393
394     // Open an output file for each stream
395     for (i=0; i<cfg.ts_number_layers; i++)
396     {
397         char file_name[512];
398         sprintf (file_name, "%s_%d.ivf", argv[2], i);
399         if (!(outfile[i] = fopen(file_name, "wb")))
400             die("Failed to open %s for writing", file_name);
401         write_ivf_file_header(outfile[i], &cfg, 0);
402     }
403
404     // Initialize codec
405     if (vpx_codec_enc_init (&codec, interface, &cfg, 0))
406         die_codec (&codec, "Failed to initialize encoder");
407
408     // Cap CPU & first I-frame size
409     vpx_codec_control (&codec, VP8E_SET_CPUUSED, -6);
410     vpx_codec_control (&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 600);
411
412     frame_avail = 1;
413     while (frame_avail || got_data) {
414         vpx_codec_iter_t iter = NULL;
415         const vpx_codec_cx_pkt_t *pkt;
416
417         flags = layer_flags[frame_cnt % cfg.ts_periodicity];
418
419         frame_avail = read_frame(infile, &raw);
420         if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
421                             1, flags, VPX_DL_REALTIME))
422             die_codec(&codec, "Failed to encode frame");
423
424         // Reset KF flag
425         layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
426
427         got_data = 0;
428         while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
429             got_data = 1;
430             switch (pkt->kind) {
431             case VPX_CODEC_CX_FRAME_PKT:
432                 for (i=cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
433                                               i<cfg.ts_number_layers; i++)
434                 {
435                     write_ivf_frame_header(outfile[i], pkt);
436                     if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
437                               outfile[i]));
438                     frames_in_layer[i]++;
439                 }
440                 break;
441             default:
442                 break;
443             }
444             printf (pkt->kind == VPX_CODEC_CX_FRAME_PKT
445                     && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
446             fflush (stdout);
447         }
448         frame_cnt++;
449     }
450     printf ("\n");
451     fclose (infile);
452
453     printf ("Processed %d frames.\n",frame_cnt-1);
454     if (vpx_codec_destroy(&codec))
455             die_codec (&codec, "Failed to destroy codec");
456
457     // Try to rewrite the output file headers with the actual frame count
458     for (i=0; i<cfg.ts_number_layers; i++)
459     {
460         if (!fseek(outfile[i], 0, SEEK_SET))
461             write_ivf_file_header (outfile[i], &cfg, frames_in_layer[i]);
462         fclose (outfile[i]);
463     }
464
465     return EXIT_SUCCESS;
466 }
467