Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / libvpx / source / libvpx / examples / vp8_set_maps.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 // VP8 Set Active and ROI Maps
13 // ===========================
14 //
15 // This is an example demonstrating how to control the VP8 encoder's
16 // ROI and Active maps.
17 //
18 // ROI (Reigon of Interest) maps are a way for the application to assign
19 // each macroblock in the image to a region, and then set quantizer and
20 // filtering parameters on that image.
21 //
22 // Active maps are a way for the application to specify on a
23 // macroblock-by-macroblock basis whether there is any activity in that
24 // macroblock.
25 //
26 //
27 // Configuration
28 // -------------
29 // An ROI map is set on frame 22. If the width of the image in macroblocks
30 // is evenly divisble by 4, then the output will appear to have distinct
31 // columns, where the quantizer, loopfilter, and static threshold differ
32 // from column to column.
33 //
34 // An active map is set on frame 33. If the width of the image in macroblocks
35 // is evenly divisble by 4, then the output will appear to have distinct
36 // columns, where one column will have motion and the next will not.
37 //
38 // The active map is cleared on frame 44.
39 //
40 // Observing The Effects
41 // ---------------------
42 // Use the `simple_decoder` example to decode this sample, and observe
43 // the change in the image at frames 22, 33, and 44.
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <stdarg.h>
48 #include <string.h>
49 #define VPX_CODEC_DISABLE_COMPAT 1
50 #include "vpx/vpx_encoder.h"
51 #include "vpx/vp8cx.h"
52 #define interface (vpx_codec_vp8_cx())
53 #define fourcc    0x30385056
54
55 #define IVF_FILE_HDR_SZ  (32)
56 #define IVF_FRAME_HDR_SZ (12)
57
58 static void mem_put_le16(char *mem, unsigned int val) {
59     mem[0] = val;
60     mem[1] = val>>8;
61 }
62
63 static void mem_put_le32(char *mem, unsigned int val) {
64     mem[0] = val;
65     mem[1] = val>>8;
66     mem[2] = val>>16;
67     mem[3] = val>>24;
68 }
69
70 static void die(const char *fmt, ...) {
71     va_list ap;
72
73     va_start(ap, fmt);
74     vprintf(fmt, ap);
75     if(fmt[strlen(fmt)-1] != '\n')
76         printf("\n");
77     exit(EXIT_FAILURE);
78 }
79
80 static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
81     const char *detail = vpx_codec_error_detail(ctx);
82
83     printf("%s: %s\n", s, vpx_codec_error(ctx));
84     if(detail)
85         printf("    %s\n",detail);
86     exit(EXIT_FAILURE);
87 }
88
89 static int read_frame(FILE *f, vpx_image_t *img) {
90     size_t nbytes, to_read;
91     int    res = 1;
92
93     to_read = img->w*img->h*3/2;
94     nbytes = fread(img->planes[0], 1, to_read, f);
95     if(nbytes != to_read) {
96         res = 0;
97         if(nbytes > 0)
98             printf("Warning: Read partial frame. Check your width & height!\n");
99     }
100     return res;
101 }
102
103 static void write_ivf_file_header(FILE *outfile,
104                                   const vpx_codec_enc_cfg_t *cfg,
105                                   int frame_cnt) {
106     char header[32];
107
108     if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
109         return;
110     header[0] = 'D';
111     header[1] = 'K';
112     header[2] = 'I';
113     header[3] = 'F';
114     mem_put_le16(header+4,  0);                   /* version */
115     mem_put_le16(header+6,  32);                  /* headersize */
116     mem_put_le32(header+8,  fourcc);              /* headersize */
117     mem_put_le16(header+12, cfg->g_w);            /* width */
118     mem_put_le16(header+14, cfg->g_h);            /* height */
119     mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
120     mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
121     mem_put_le32(header+24, frame_cnt);           /* length */
122     mem_put_le32(header+28, 0);                   /* unused */
123
124     (void) fwrite(header, 1, 32, outfile);
125 }
126
127
128 static void write_ivf_frame_header(FILE *outfile,
129                                    const vpx_codec_cx_pkt_t *pkt)
130 {
131     char             header[12];
132     vpx_codec_pts_t  pts;
133
134     if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
135         return;
136
137     pts = pkt->data.frame.pts;
138     mem_put_le32(header, pkt->data.frame.sz);
139     mem_put_le32(header+4, pts&0xFFFFFFFF);
140     mem_put_le32(header+8, pts >> 32);
141
142     (void) fwrite(header, 1, 12, outfile);
143 }
144
145 int main(int argc, char **argv) {
146     FILE                *infile, *outfile;
147     vpx_codec_ctx_t      codec;
148     vpx_codec_enc_cfg_t  cfg;
149     int                  frame_cnt = 0;
150     vpx_image_t          raw;
151     vpx_codec_err_t      res;
152     long                 width;
153     long                 height;
154     int                  frame_avail;
155     int                  got_data;
156     int                  flags = 0;
157
158     /* Open files */
159     if(argc!=5)
160         die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
161     width = strtol(argv[1], NULL, 0);
162     height = strtol(argv[2], NULL, 0);
163     if(width < 16 || width%2 || height <16 || height%2)
164         die("Invalid resolution: %ldx%ld", width, height);
165     if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
166         die("Faile to allocate image", width, height);
167     if(!(outfile = fopen(argv[4], "wb")))
168         die("Failed to open %s for writing", argv[4]);
169
170     printf("Using %s\n",vpx_codec_iface_name(interface));
171
172     /* Populate encoder configuration */
173     res = vpx_codec_enc_config_default(interface, &cfg, 0);
174     if(res) {
175         printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
176         return EXIT_FAILURE;
177     }
178
179     /* Update the default configuration with our settings */
180     cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
181                             / cfg.g_w / cfg.g_h;
182     cfg.g_w = width;
183     cfg.g_h = height;
184
185     write_ivf_file_header(outfile, &cfg, 0);
186
187
188         /* Open input file for this encoding pass */
189         if(!(infile = fopen(argv[3], "rb")))
190             die("Failed to open %s for reading", argv[3]);
191
192         /* Initialize codec */
193         if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
194             die_codec(&codec, "Failed to initialize encoder");
195
196         frame_avail = 1;
197         got_data = 0;
198         while(frame_avail || got_data) {
199             vpx_codec_iter_t iter = NULL;
200             const vpx_codec_cx_pkt_t *pkt;
201
202             if(frame_cnt + 1 == 22) {
203                 vpx_roi_map_t  roi;
204                 unsigned int   i;
205
206                 roi.rows = cfg.g_h/16;
207                 roi.cols = cfg.g_w/16;
208
209                 roi.delta_q[0] = 0;
210                 roi.delta_q[1] = -2;
211                 roi.delta_q[2] = -4;
212                 roi.delta_q[3] = -6;
213
214                 roi.delta_lf[0] = 0;
215                 roi.delta_lf[1] = 1;
216                 roi.delta_lf[2] = 2;
217                 roi.delta_lf[3] = 3;
218
219                 roi.static_threshold[0] = 1500;
220                 roi.static_threshold[1] = 1000;
221                 roi.static_threshold[2] =  500;
222                 roi.static_threshold[3] =    0;
223
224                 /* generate an ROI map for example */
225                 roi.roi_map = malloc(roi.rows * roi.cols);
226                 for(i=0;i<roi.rows*roi.cols;i++)
227                     roi.roi_map[i] = i & 3;
228
229                 if(vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))
230                     die_codec(&codec, "Failed to set ROI map");
231
232                 free(roi.roi_map);
233             } else if(frame_cnt + 1 == 33) {
234                 vpx_active_map_t  active;
235                 unsigned int      i;
236
237                 active.rows = cfg.g_h/16;
238                 active.cols = cfg.g_w/16;
239
240                 /* generate active map for example */
241                 active.active_map = malloc(active.rows * active.cols);
242                 for(i=0;i<active.rows*active.cols;i++)
243                     active.active_map[i] = i & 1;
244
245                 if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))
246                     die_codec(&codec, "Failed to set active map");
247
248                 free(active.active_map);
249             } else if(frame_cnt + 1 == 44) {
250                 vpx_active_map_t  active;
251
252                 active.rows = cfg.g_h/16;
253                 active.cols = cfg.g_w/16;
254
255                 /* pass in null map to disable active_map*/
256                 active.active_map = NULL;
257
258                 if(vpx_codec_control(&codec, VP8E_SET_ACTIVEMAP, &active))
259                     die_codec(&codec, "Failed to set active map");
260             }
261             frame_avail = read_frame(infile, &raw);
262             if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
263                                 1, flags, VPX_DL_REALTIME))
264                 die_codec(&codec, "Failed to encode frame");
265             got_data = 0;
266             while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
267                 got_data = 1;
268                 switch(pkt->kind) {
269                 case VPX_CODEC_CX_FRAME_PKT:
270                     write_ivf_frame_header(outfile, pkt);
271                     (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
272                                   outfile);
273                     break;
274                 default:
275                     break;
276                 }
277                 printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
278                        && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
279                 fflush(stdout);
280             }
281             frame_cnt++;
282         }
283         printf("\n");
284         fclose(infile);
285
286     printf("Processed %d frames.\n",frame_cnt-1);
287     vpx_img_free(&raw);
288     if(vpx_codec_destroy(&codec))
289         die_codec(&codec, "Failed to destroy codec");
290
291     /* Try to rewrite the file header with the actual frame count */
292     if(!fseek(outfile, 0, SEEK_SET))
293         write_ivf_file_header(outfile, &cfg, frame_cnt-1);
294     fclose(outfile);
295     return EXIT_SUCCESS;
296 }