## ffmpeg / libavcodec / mpegvideo.c @ 13b54752

History | View | Annotate | Download (41.1 KB)

1 | de6d9b64 | Fabrice Bellard | ```
/*
``` |
---|---|---|---|

2 | ```
* The simplest mpeg encoder (well, it was the simplest!)
``` |
||

3 | ```
* Copyright (c) 2000,2001 Gerard Lantau.
``` |
||

4 | ```
*
``` |
||

5 | ```
* This program is free software; you can redistribute it and/or modify
``` |
||

6 | ```
* it under the terms of the GNU General Public License as published by
``` |
||

7 | ```
* the Free Software Foundation; either version 2 of the License, or
``` |
||

8 | ```
* (at your option) any later version.
``` |
||

9 | ```
*
``` |
||

10 | ```
* This program is distributed in the hope that it will be useful,
``` |
||

11 | ```
* but WITHOUT ANY WARRANTY; without even the implied warranty of
``` |
||

12 | ```
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
``` |
||

13 | ```
* GNU General Public License for more details.
``` |
||

14 | ```
*
``` |
||

15 | ```
* You should have received a copy of the GNU General Public License
``` |
||

16 | ```
* along with this program; if not, write to the Free Software
``` |
||

17 | ```
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
``` |
||

18 | ```
*/
``` |
||

19 | #include <stdlib.h> |
||

20 | #include <stdio.h> |
||

21 | #include <math.h> |
||

22 | #include <string.h> |
||

23 | #include "avcodec.h" |
||

24 | #include "dsputil.h" |
||

25 | #include "mpegvideo.h" |
||

26 | |||

27 | 54329dd5 | Nick Kurshev | ```
#ifdef USE_FASTMEMCPY
``` |

28 | #include "fastmemcpy.h" |
||

29 | ```
#endif
``` |
||

30 | |||

31 | 21af69f7 | Fabrice Bellard | static void encode_picture(MpegEncContext *s, int picture_number); |

32 | static void rate_control_init(MpegEncContext *s); |
||

33 | static int rate_estimate_qscale(MpegEncContext *s); |
||

34 | static void dct_unquantize_mpeg1_c(MpegEncContext *s, |
||

35 | DCTELEM *block, int n, int qscale); |
||

36 | static void dct_unquantize_h263_c(MpegEncContext *s, |
||

37 | DCTELEM *block, int n, int qscale); |
||

38 | static int dct_quantize(MpegEncContext *s, DCTELEM *block, int n, int qscale); |
||

39 | static int dct_quantize_mmx(MpegEncContext *s, |
||

40 | ```
DCTELEM *block, int n,
``` |
||

41 | ```
int qscale);
``` |
||

42 | de6d9b64 | Fabrice Bellard | #define EDGE_WIDTH 16 |

43 | |||

44 | ```
/* enable all paranoid tests for rounding, overflows, etc... */
``` |
||

45 | ```
//#define PARANOID
``` |
||

46 | |||

47 | ```
//#define DEBUG
``` |
||

48 | |||

49 | ```
/* for jpeg fast DCT */
``` |
||

50 | #define CONST_BITS 14 |
||

51 | |||

52 | static const unsigned short aanscales[64] = { |
||

53 | ```
/* precomputed values scaled up by 14 bits */
``` |
||

54 | 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, |
||

55 | 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, |
||

56 | 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, |
||

57 | 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, |
||

58 | 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, |
||

59 | 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, |
||

60 | 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, |
||

61 | 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 |
||

62 | }; |
||

63 | |||

64 | static UINT8 h263_chroma_roundtab[16] = { |
||

65 | 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, |
||

66 | }; |
||

67 | |||

68 | ```
/* default motion estimation */
``` |
||

69 | ```
int motion_estimation_method = ME_LOG;
``` |
||

70 | |||

71 | ```
/* XXX: should use variable shift ? */
``` |
||

72 | #define QMAT_SHIFT_MMX 19 |
||

73 | #define QMAT_SHIFT 25 |
||

74 | |||

75 | static void convert_matrix(int *qmat, const UINT16 *quant_matrix, int qscale) |
||

76 | { |
||

77 | ```
int i;
``` |
||

78 | |||

79 | ```
if (av_fdct == jpeg_fdct_ifast) {
``` |
||

80 | for(i=0;i<64;i++) { |
||

81 | ```
/* 16 <= qscale * quant_matrix[i] <= 7905 */
``` |
||

82 | ```
/* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */
``` |
||

83 | |||

84 | qmat[i] = (int)((1ULL << (QMAT_SHIFT + 11)) / (aanscales[i] * qscale * quant_matrix[i])); |
||

85 | } |
||

86 | ```
} else {
``` |
||

87 | for(i=0;i<64;i++) { |
||

88 | ```
/* We can safely suppose that 16 <= quant_matrix[i] <= 255
``` |
||

89 | ```
So 16 <= qscale * quant_matrix[i] <= 7905
``` |
||

90 | ```
so (1 << QMAT_SHIFT) / 16 >= qmat[i] >= (1 << QMAT_SHIFT) / 7905
``` |
||

91 | ```
*/
``` |
||

92 | ```
qmat[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]);
``` |
||

93 | } |
||

94 | } |
||

95 | } |
||

96 | |||

97 | ```
/* init common structure for both encoder and decoder */
``` |
||

98 | ```
int MPV_common_init(MpegEncContext *s)
``` |
||

99 | { |
||

100 | ```
int c_size, i;
``` |
||

101 | UINT8 *pict; |
||

102 | |||

103 | 21af69f7 | Fabrice Bellard | ```
if (s->out_format == FMT_H263)
``` |

104 | s->dct_unquantize = dct_unquantize_h263_c; |
||

105 | ```
else
``` |
||

106 | s->dct_unquantize = dct_unquantize_mpeg1_c; |
||

107 | |||

108 | ```
#ifdef HAVE_MMX
``` |
||

109 | MPV_common_init_mmx(s); |
||

110 | a9b3f630 | Nick Kurshev | ```
#endif
``` |

111 | de6d9b64 | Fabrice Bellard | s->mb_width = (s->width + 15) / 16; |

112 | s->mb_height = (s->height + 15) / 16; |
||

113 | s->linesize = s->mb_width * 16 + 2 * EDGE_WIDTH; |
||

114 | |||

115 | for(i=0;i<3;i++) { |
||

116 | ```
int w, h, shift, pict_start;
``` |
||

117 | |||

118 | w = s->linesize; |
||

119 | h = s->mb_height * 16 + 2 * EDGE_WIDTH; |
||

120 | shift = (i == 0) ? 0 : 1; |
||

121 | c_size = (w >> shift) * (h >> shift); |
||

122 | pict_start = (w >> shift) * (EDGE_WIDTH >> shift) + (EDGE_WIDTH >> shift); |
||

123 | |||

124 | pict = av_mallocz(c_size); |
||

125 | if (pict == NULL) |
||

126 | ```
goto fail;
``` |
||

127 | s->last_picture_base[i] = pict; |
||

128 | s->last_picture[i] = pict + pict_start; |
||

129 | |||

130 | pict = av_mallocz(c_size); |
||

131 | if (pict == NULL) |
||

132 | ```
goto fail;
``` |
||

133 | s->next_picture_base[i] = pict; |
||

134 | s->next_picture[i] = pict + pict_start; |
||

135 | |||

136 | ```
if (s->has_b_frames) {
``` |
||

137 | pict = av_mallocz(c_size); |
||

138 | if (pict == NULL) |
||

139 | ```
goto fail;
``` |
||

140 | s->aux_picture_base[i] = pict; |
||

141 | s->aux_picture[i] = pict + pict_start; |
||

142 | } |
||

143 | } |
||

144 | |||

145 | ```
if (s->out_format == FMT_H263) {
``` |
||

146 | ```
int size;
``` |
||

147 | ```
/* MV prediction */
``` |
||

148 | size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2); |
||

149 | s->motion_val = malloc(size * 2 * sizeof(INT16)); |
||

150 | if (s->motion_val == NULL) |
||

151 | ```
goto fail;
``` |
||

152 | memset(s->motion_val, 0, size * 2 * sizeof(INT16)); |
||

153 | } |
||

154 | |||

155 | ```
if (s->h263_pred) {
``` |
||

156 | ```
int y_size, c_size, i, size;
``` |
||

157 | |||

158 | ```
/* dc values */
``` |
||

159 | |||

160 | y_size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2); |
||

161 | c_size = (s->mb_width + 2) * (s->mb_height + 2); |
||

162 | ```
size = y_size + 2 * c_size;
``` |
||

163 | s->dc_val[0] = malloc(size * sizeof(INT16)); |
||

164 | if (s->dc_val[0] == NULL) |
||

165 | ```
goto fail;
``` |
||

166 | s->dc_val[1] = s->dc_val[0] + y_size; |
||

167 | s->dc_val[2] = s->dc_val[1] + c_size; |
||

168 | for(i=0;i<size;i++) |
||

169 | s->dc_val[0][i] = 1024; |
||

170 | |||

171 | ```
/* ac values */
``` |
||

172 | s->ac_val[0] = av_mallocz(size * sizeof(INT16) * 16); |
||

173 | if (s->ac_val[0] == NULL) |
||

174 | ```
goto fail;
``` |
||

175 | s->ac_val[1] = s->ac_val[0] + y_size; |
||

176 | s->ac_val[2] = s->ac_val[1] + c_size; |
||

177 | |||

178 | ```
/* cbp values */
``` |
||

179 | s->coded_block = av_mallocz(y_size); |
||

180 | ```
if (!s->coded_block)
``` |
||

181 | ```
goto fail;
``` |
||

182 | } |
||

183 | ```
/* default structure is frame */
``` |
||

184 | s->picture_structure = PICT_FRAME; |
||

185 | |||

186 | ```
/* init default q matrix (only for mpeg and mjpeg) */
``` |
||

187 | for(i=0;i<64;i++) { |
||

188 | s->intra_matrix[i] = default_intra_matrix[i]; |
||

189 | s->chroma_intra_matrix[i] = default_intra_matrix[i]; |
||

190 | s->non_intra_matrix[i] = default_non_intra_matrix[i]; |
||

191 | s->chroma_non_intra_matrix[i] = default_non_intra_matrix[i]; |
||

192 | } |
||

193 | 3bb4e23a | Fabrice Bellard | ```
/* init macroblock skip table */
``` |

194 | ```
if (!s->encoding) {
``` |
||

195 | s->mbskip_table = av_mallocz(s->mb_width * s->mb_height); |
||

196 | ```
if (!s->mbskip_table)
``` |
||

197 | ```
goto fail;
``` |
||

198 | } |
||

199 | |||

200 | de6d9b64 | Fabrice Bellard | ```
s->context_initialized = 1;
``` |

201 | return 0; |
||

202 | ```
fail:
``` |
||

203 | ```
if (s->motion_val)
``` |
||

204 | free(s->motion_val); |
||

205 | if (s->dc_val[0]) |
||

206 | ```
free(s->dc_val[0]);
``` |
||

207 | if (s->ac_val[0]) |
||

208 | ```
free(s->ac_val[0]);
``` |
||

209 | ```
if (s->coded_block)
``` |
||

210 | free(s->coded_block); |
||

211 | 3bb4e23a | Fabrice Bellard | ```
if (s->mbskip_table)
``` |

212 | free(s->mbskip_table); |
||

213 | de6d9b64 | Fabrice Bellard | for(i=0;i<3;i++) { |

214 | ```
if (s->last_picture_base[i])
``` |
||

215 | free(s->last_picture_base[i]); |
||

216 | ```
if (s->next_picture_base[i])
``` |
||

217 | free(s->next_picture_base[i]); |
||

218 | ```
if (s->aux_picture_base[i])
``` |
||

219 | free(s->aux_picture_base[i]); |
||

220 | } |
||

221 | return -1; |
||

222 | } |
||

223 | |||

224 | ```
/* init common structure for both encoder and decoder */
``` |
||

225 | ```
void MPV_common_end(MpegEncContext *s)
``` |
||

226 | { |
||

227 | ```
int i;
``` |
||

228 | |||

229 | ```
if (s->motion_val)
``` |
||

230 | free(s->motion_val); |
||

231 | ```
if (s->h263_pred) {
``` |
||

232 | ```
free(s->dc_val[0]);
``` |
||

233 | ```
free(s->ac_val[0]);
``` |
||

234 | free(s->coded_block); |
||

235 | } |
||

236 | 3bb4e23a | Fabrice Bellard | ```
if (s->mbskip_table)
``` |

237 | free(s->mbskip_table); |
||

238 | de6d9b64 | Fabrice Bellard | for(i=0;i<3;i++) { |

239 | free(s->last_picture_base[i]); |
||

240 | free(s->next_picture_base[i]); |
||

241 | ```
if (s->has_b_frames)
``` |
||

242 | free(s->aux_picture_base[i]); |
||

243 | } |
||

244 | ```
s->context_initialized = 0;
``` |
||

245 | } |
||

246 | |||

247 | ```
/* init video encoder */
``` |
||

248 | ```
int MPV_encode_init(AVCodecContext *avctx)
``` |
||

249 | { |
||

250 | MpegEncContext *s = avctx->priv_data; |
||

251 | |||

252 | s->bit_rate = avctx->bit_rate; |
||

253 | s->frame_rate = avctx->frame_rate; |
||

254 | s->width = avctx->width; |
||

255 | s->height = avctx->height; |
||

256 | s->gop_size = avctx->gop_size; |
||

257 | if (s->gop_size <= 1) { |
||

258 | ```
s->intra_only = 1;
``` |
||

259 | ```
s->gop_size = 12;
``` |
||

260 | ```
} else {
``` |
||

261 | ```
s->intra_only = 0;
``` |
||

262 | } |
||

263 | s->full_search = motion_estimation_method; |
||

264 | |||

265 | s->fixed_qscale = (avctx->flags & CODEC_FLAG_QSCALE); |
||

266 | |||

267 | ```
switch(avctx->codec->id) {
``` |
||

268 | ```
case CODEC_ID_MPEG1VIDEO:
``` |
||

269 | s->out_format = FMT_MPEG1; |
||

270 | ```
break;
``` |
||

271 | ```
case CODEC_ID_MJPEG:
``` |
||

272 | s->out_format = FMT_MJPEG; |
||

273 | s->intra_only = 1; /* force intra only for jpeg */ |
||

274 | if (mjpeg_init(s) < 0) |
||

275 | return -1; |
||

276 | ```
break;
``` |
||

277 | ```
case CODEC_ID_H263:
``` |
||

278 | if (h263_get_picture_format(s->width, s->height) == 7) |
||

279 | return -1; |
||

280 | s->out_format = FMT_H263; |
||

281 | ```
break;
``` |
||

282 | ```
case CODEC_ID_H263P:
``` |
||

283 | s->out_format = FMT_H263; |
||

284 | ```
s->h263_plus = 1;
``` |
||

285 | ```
/* XXX: not unrectricted mv yet */
``` |
||

286 | ```
break;
``` |
||

287 | ```
case CODEC_ID_RV10:
``` |
||

288 | s->out_format = FMT_H263; |
||

289 | ```
s->h263_rv10 = 1;
``` |
||

290 | ```
break;
``` |
||

291 | ```
case CODEC_ID_OPENDIVX:
``` |
||

292 | s->out_format = FMT_H263; |
||

293 | ```
s->h263_pred = 1;
``` |
||

294 | ```
s->unrestricted_mv = 1;
``` |
||

295 | ```
break;
``` |
||

296 | ```
case CODEC_ID_MSMPEG4:
``` |
||

297 | s->out_format = FMT_H263; |
||

298 | ```
s->h263_msmpeg4 = 1;
``` |
||

299 | ```
s->h263_pred = 1;
``` |
||

300 | ```
s->unrestricted_mv = 1;
``` |
||

301 | ```
break;
``` |
||

302 | ```
default:
``` |
||

303 | return -1; |
||

304 | } |
||

305 | |||

306 | ```
if (s->out_format == FMT_H263)
``` |
||

307 | h263_encode_init_vlc(s); |
||

308 | |||

309 | 3bb4e23a | Fabrice Bellard | ```
s->encoding = 1;
``` |

310 | |||

311 | de6d9b64 | Fabrice Bellard | ```
/* init */
``` |

312 | if (MPV_common_init(s) < 0) |
||

313 | return -1; |
||

314 | |||

315 | ```
/* rate control init */
``` |
||

316 | rate_control_init(s); |
||

317 | |||

318 | ```
s->picture_number = 0;
``` |
||

319 | ```
s->fake_picture_number = 0;
``` |
||

320 | ```
/* motion detector init */
``` |
||

321 | ```
s->f_code = 1;
``` |
||

322 | |||

323 | return 0; |
||

324 | } |
||

325 | |||

326 | ```
int MPV_encode_end(AVCodecContext *avctx)
``` |
||

327 | { |
||

328 | MpegEncContext *s = avctx->priv_data; |
||

329 | |||

330 | ```
#ifdef STATS
``` |
||

331 | print_stats(); |
||

332 | ```
#endif
``` |
||

333 | MPV_common_end(s); |
||

334 | ```
if (s->out_format == FMT_MJPEG)
``` |
||

335 | mjpeg_close(s); |
||

336 | return 0; |
||

337 | } |
||

338 | |||

339 | ```
/* draw the edges of width 'w' of an image of size width, height */
``` |
||

340 | static void draw_edges(UINT8 *buf, int wrap, int width, int height, int w) |
||

341 | { |
||

342 | UINT8 *ptr, *last_line; |
||

343 | ```
int i;
``` |
||

344 | |||

345 | ```
last_line = buf + (height - 1) * wrap;
``` |
||

346 | for(i=0;i<w;i++) { |
||

347 | ```
/* top and bottom */
``` |
||

348 | ```
memcpy(buf - (i + 1) * wrap, buf, width);
``` |
||

349 | ```
memcpy(last_line + (i + 1) * wrap, last_line, width);
``` |
||

350 | } |
||

351 | ```
/* left and right */
``` |
||

352 | ptr = buf; |
||

353 | for(i=0;i<height;i++) { |
||

354 | ```
memset(ptr - w, ptr[0], w);
``` |
||

355 | ```
memset(ptr + width, ptr[width-1], w);
``` |
||

356 | ptr += wrap; |
||

357 | } |
||

358 | ```
/* corners */
``` |
||

359 | for(i=0;i<w;i++) { |
||

360 | memset(buf - (i + 1) * wrap - w, buf[0], w); /* top left */ |
||

361 | memset(buf - (i + 1) * wrap + width, buf[width-1], w); /* top right */ |
||

362 | memset(last_line + (i + 1) * wrap - w, last_line[0], w); /* top left */ |
||

363 | memset(last_line + (i + 1) * wrap + width, last_line[width-1], w); /* top right */ |
||

364 | } |
||

365 | } |
||

366 | |||

367 | ```
/* generic function for encode/decode called before a frame is coded/decoded */
``` |
||

368 | ```
void MPV_frame_start(MpegEncContext *s)
``` |
||

369 | { |
||

370 | ```
int i;
``` |
||

371 | UINT8 *tmp; |
||

372 | |||

373 | ```
if (s->pict_type == B_TYPE) {
``` |
||

374 | for(i=0;i<3;i++) { |
||

375 | s->current_picture[i] = s->aux_picture[i]; |
||

376 | } |
||

377 | ```
} else {
``` |
||

378 | for(i=0;i<3;i++) { |
||

379 | ```
/* swap next and last */
``` |
||

380 | tmp = s->last_picture[i]; |
||

381 | s->last_picture[i] = s->next_picture[i]; |
||

382 | s->next_picture[i] = tmp; |
||

383 | s->current_picture[i] = tmp; |
||

384 | } |
||

385 | } |
||

386 | } |
||

387 | 21af69f7 | Fabrice Bellard | |

388 | de6d9b64 | Fabrice Bellard | ```
/* generic function for encode/decode called after a frame has been coded/decoded */
``` |

389 | ```
void MPV_frame_end(MpegEncContext *s)
``` |
||

390 | { |
||

391 | ```
/* draw edge for correct motion prediction if outside */
``` |
||

392 | ```
if (s->pict_type != B_TYPE) {
``` |
||

393 | ```
draw_edges(s->current_picture[0], s->linesize, s->width, s->height, EDGE_WIDTH);
``` |
||

394 | draw_edges(s->current_picture[1], s->linesize/2, s->width/2, s->height/2, EDGE_WIDTH/2); |
||

395 | draw_edges(s->current_picture[2], s->linesize/2, s->width/2, s->height/2, EDGE_WIDTH/2); |
||

396 | } |
||

397 | } |
||

398 | |||

399 | ```
int MPV_encode_picture(AVCodecContext *avctx,
``` |
||

400 | unsigned char *buf, int buf_size, void *data) |
||

401 | { |
||

402 | MpegEncContext *s = avctx->priv_data; |
||

403 | AVPicture *pict = data; |
||

404 | ```
int i, j;
``` |
||

405 | |||

406 | ```
if (s->fixed_qscale)
``` |
||

407 | s->qscale = avctx->quality; |
||

408 | |||

409 | init_put_bits(&s->pb, buf, buf_size, NULL, NULL); |
||

410 | |||

411 | ```
if (!s->intra_only) {
``` |
||

412 | ```
/* first picture of GOP is intra */
``` |
||

413 | if ((s->picture_number % s->gop_size) == 0) |
||

414 | s->pict_type = I_TYPE; |
||

415 | ```
else
``` |
||

416 | s->pict_type = P_TYPE; |
||

417 | ```
} else {
``` |
||

418 | s->pict_type = I_TYPE; |
||

419 | } |
||

420 | avctx->key_frame = (s->pict_type == I_TYPE); |
||

421 | |||

422 | MPV_frame_start(s); |
||

423 | |||

424 | for(i=0;i<3;i++) { |
||

425 | UINT8 *src = pict->data[i]; |
||

426 | UINT8 *dest = s->current_picture[i]; |
||

427 | ```
int src_wrap = pict->linesize[i];
``` |
||

428 | ```
int dest_wrap = s->linesize;
``` |
||

429 | ```
int w = s->width;
``` |
||

430 | ```
int h = s->height;
``` |
||

431 | |||

432 | if (i >= 1) { |
||

433 | ```
dest_wrap >>= 1;
``` |
||

434 | ```
w >>= 1;
``` |
||

435 | ```
h >>= 1;
``` |
||

436 | } |
||

437 | |||

438 | for(j=0;j<h;j++) { |
||

439 | memcpy(dest, src, w); |
||

440 | dest += dest_wrap; |
||

441 | src += src_wrap; |
||

442 | } |
||

443 | s->new_picture[i] = s->current_picture[i]; |
||

444 | } |
||

445 | |||

446 | encode_picture(s, s->picture_number); |
||

447 | |||

448 | MPV_frame_end(s); |
||

449 | s->picture_number++; |
||

450 | |||

451 | ```
if (s->out_format == FMT_MJPEG)
``` |
||

452 | mjpeg_picture_trailer(s); |
||

453 | |||

454 | flush_put_bits(&s->pb); |
||

455 | ```
s->total_bits += (s->pb.buf_ptr - s->pb.buf) * 8;
``` |
||

456 | avctx->quality = s->qscale; |
||

457 | ```
return s->pb.buf_ptr - s->pb.buf;
``` |
||

458 | } |
||

459 | |||

460 | static inline int clip(int a, int amin, int amax) |
||

461 | { |
||

462 | ```
if (a < amin)
``` |
||

463 | ```
return amin;
``` |
||

464 | else if (a > amax) |
||

465 | ```
return amax;
``` |
||

466 | ```
else
``` |
||

467 | ```
return a;
``` |
||

468 | } |
||

469 | |||

470 | ```
/* apply one mpeg motion vector to the three components */
``` |
||

471 | static inline void mpeg_motion(MpegEncContext *s, |
||

472 | UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, |
||

473 | ```
int dest_offset,
``` |
||

474 | ```
UINT8 **ref_picture, int src_offset,
``` |
||

475 | ```
int field_based, op_pixels_func *pix_op,
``` |
||

476 | int motion_x, int motion_y, int h) |
||

477 | { |
||

478 | UINT8 *ptr; |
||

479 | ```
int dxy, offset, mx, my, src_x, src_y, height, linesize;
``` |
||

480 | |||

481 | dxy = ((motion_y & 1) << 1) | (motion_x & 1); |
||

482 | src_x = s->mb_x * 16 + (motion_x >> 1); |
||

483 | src_y = s->mb_y * (16 >> field_based) + (motion_y >> 1); |
||

484 | |||

485 | ```
/* WARNING: do no forget half pels */
``` |
||

486 | height = s->height >> field_based; |
||

487 | ```
src_x = clip(src_x, -16, s->width);
``` |
||

488 | ```
if (src_x == s->width)
``` |
||

489 | ```
dxy &= ~1;
``` |
||

490 | ```
src_y = clip(src_y, -16, height);
``` |
||

491 | ```
if (src_y == height)
``` |
||

492 | ```
dxy &= ~2;
``` |
||

493 | linesize = s->linesize << field_based; |
||

494 | ```
ptr = ref_picture[0] + (src_y * linesize) + (src_x) + src_offset;
``` |
||

495 | dest_y += dest_offset; |
||

496 | pix_op[dxy](dest_y, ptr, linesize, h); |
||

497 | pix_op[dxy](dest_y + 8, ptr + 8, linesize, h); |
||

498 | |||

499 | ```
if (s->out_format == FMT_H263) {
``` |
||

500 | ```
dxy = 0;
``` |
||

501 | if ((motion_x & 3) != 0) |
||

502 | ```
dxy |= 1;
``` |
||

503 | if ((motion_y & 3) != 0) |
||

504 | ```
dxy |= 2;
``` |
||

505 | ```
mx = motion_x >> 2;
``` |
||

506 | ```
my = motion_y >> 2;
``` |
||

507 | ```
} else {
``` |
||

508 | ```
mx = motion_x / 2;
``` |
||

509 | ```
my = motion_y / 2;
``` |
||

510 | dxy = ((my & 1) << 1) | (mx & 1); |
||

511 | ```
mx >>= 1;
``` |
||

512 | ```
my >>= 1;
``` |
||

513 | } |
||

514 | |||

515 | ```
src_x = s->mb_x * 8 + mx;
``` |
||

516 | ```
src_y = s->mb_y * (8 >> field_based) + my;
``` |
||

517 | src_x = clip(src_x, -8, s->width >> 1); |
||

518 | if (src_x == (s->width >> 1)) |
||

519 | ```
dxy &= ~1;
``` |
||

520 | src_y = clip(src_y, -8, height >> 1); |
||

521 | if (src_y == (height >> 1)) |
||

522 | ```
dxy &= ~2;
``` |
||

523 | |||

524 | offset = (src_y * (linesize >> 1)) + src_x + (src_offset >> 1); |
||

525 | ```
ptr = ref_picture[1] + offset;
``` |
||

526 | pix_op[dxy](dest_cb + (dest_offset >> 1), ptr, linesize >> 1, h >> 1); |
||

527 | ```
ptr = ref_picture[2] + offset;
``` |
||

528 | pix_op[dxy](dest_cr + (dest_offset >> 1), ptr, linesize >> 1, h >> 1); |
||

529 | } |
||

530 | |||

531 | static inline void MPV_motion(MpegEncContext *s, |
||

532 | UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, |
||

533 | ```
int dir, UINT8 **ref_picture,
``` |
||

534 | op_pixels_func *pix_op) |
||

535 | { |
||

536 | ```
int dxy, offset, mx, my, src_x, src_y, motion_x, motion_y;
``` |
||

537 | ```
int mb_x, mb_y, i;
``` |
||

538 | UINT8 *ptr, *dest; |
||

539 | |||

540 | mb_x = s->mb_x; |
||

541 | mb_y = s->mb_y; |
||

542 | |||

543 | ```
switch(s->mv_type) {
``` |
||

544 | ```
case MV_TYPE_16X16:
``` |
||

545 | ```
mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
``` |
||

546 | ```
ref_picture, 0,
``` |
||

547 | ```
0, pix_op,
``` |
||

548 | s->mv[dir][0][0], s->mv[dir][0][1], 16); |
||

549 | ```
break;
``` |
||

550 | ```
case MV_TYPE_8X8:
``` |
||

551 | for(i=0;i<4;i++) { |
||

552 | ```
motion_x = s->mv[dir][i][0];
``` |
||

553 | ```
motion_y = s->mv[dir][i][1];
``` |
||

554 | |||

555 | dxy = ((motion_y & 1) << 1) | (motion_x & 1); |
||

556 | src_x = mb_x * 16 + (motion_x >> 1) + (i & 1) * 8; |
||

557 | src_y = mb_y * 16 + (motion_y >> 1) + ((i >> 1) & 1) * 8; |
||

558 | |||

559 | ```
/* WARNING: do no forget half pels */
``` |
||

560 | ```
src_x = clip(src_x, -16, s->width);
``` |
||

561 | ```
if (src_x == s->width)
``` |
||

562 | ```
dxy &= ~1;
``` |
||

563 | ```
src_y = clip(src_y, -16, s->height);
``` |
||

564 | ```
if (src_y == s->height)
``` |
||

565 | ```
dxy &= ~2;
``` |
||

566 | |||

567 | ```
ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);
``` |
||

568 | dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; |
||

569 | ```
pix_op[dxy](dest, ptr, s->linesize, 8);
``` |
||

570 | } |
||

571 | ```
/* In case of 8X8, we construct a single chroma motion vector
``` |
||

572 | ```
with a special rounding */
``` |
||

573 | ```
mx = 0;
``` |
||

574 | ```
my = 0;
``` |
||

575 | for(i=0;i<4;i++) { |
||

576 | ```
mx += s->mv[dir][i][0];
``` |
||

577 | ```
my += s->mv[dir][i][1];
``` |
||

578 | } |
||

579 | if (mx >= 0) |
||

580 | mx = (h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1)); |
||

581 | ```
else {
``` |
||

582 | mx = -mx; |
||

583 | mx = -(h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1)); |
||

584 | } |
||

585 | if (my >= 0) |
||

586 | my = (h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1)); |
||

587 | ```
else {
``` |
||

588 | my = -my; |
||

589 | my = -(h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1)); |
||

590 | } |
||

591 | dxy = ((my & 1) << 1) | (mx & 1); |
||

592 | ```
mx >>= 1;
``` |
||

593 | ```
my >>= 1;
``` |
||

594 | |||

595 | ```
src_x = mb_x * 8 + mx;
``` |
||

596 | ```
src_y = mb_y * 8 + my;
``` |
||

597 | src_x = clip(src_x, -8, s->width/2); |
||

598 | if (src_x == s->width/2) |
||

599 | ```
dxy &= ~1;
``` |
||

600 | src_y = clip(src_y, -8, s->height/2); |
||

601 | if (src_y == s->height/2) |
||

602 | ```
dxy &= ~2;
``` |
||

603 | |||

604 | ```
offset = (src_y * (s->linesize >> 1)) + src_x;
``` |
||

605 | ```
ptr = ref_picture[1] + offset;
``` |
||

606 | pix_op[dxy](dest_cb, ptr, s->linesize >> 1, 8); |
||

607 | ```
ptr = ref_picture[2] + offset;
``` |
||

608 | pix_op[dxy](dest_cr, ptr, s->linesize >> 1, 8); |
||

609 | ```
break;
``` |
||

610 | ```
case MV_TYPE_FIELD:
``` |
||

611 | ```
if (s->picture_structure == PICT_FRAME) {
``` |
||

612 | ```
/* top field */
``` |
||

613 | ```
mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
``` |
||

614 | ref_picture, s->field_select[dir][0] ? s->linesize : 0, |
||

615 | ```
1, pix_op,
``` |
||

616 | s->mv[dir][0][0], s->mv[dir][0][1], 8); |
||

617 | ```
/* bottom field */
``` |
||

618 | mpeg_motion(s, dest_y, dest_cb, dest_cr, s->linesize, |
||

619 | ref_picture, s->field_select[dir][1] ? s->linesize : 0, |
||

620 | ```
1, pix_op,
``` |
||

621 | s->mv[dir][1][0], s->mv[dir][1][1], 8); |
||

622 | ```
} else {
``` |
||

623 | |||

624 | |||

625 | } |
||

626 | ```
break;
``` |
||

627 | } |
||

628 | } |
||

629 | |||

630 | |||

631 | ```
/* put block[] to dest[] */
``` |
||

632 | static inline void put_dct(MpegEncContext *s, |
||

633 | DCTELEM *block, int i, UINT8 *dest, int line_size) |
||

634 | { |
||

635 | ```
if (!s->mpeg2)
``` |
||

636 | 21af69f7 | Fabrice Bellard | s->dct_unquantize(s, block, i, s->qscale); |

637 | 4af7bcc1 | Arpi | ff_idct (block); |

638 | de6d9b64 | Fabrice Bellard | put_pixels_clamped(block, dest, line_size); |

639 | } |
||

640 | |||

641 | ```
/* add block[] to dest[] */
``` |
||

642 | static inline void add_dct(MpegEncContext *s, |
||

643 | DCTELEM *block, int i, UINT8 *dest, int line_size) |
||

644 | { |
||

645 | if (s->block_last_index[i] >= 0) { |
||

646 | ```
if (!s->mpeg2)
``` |
||

647 | 21af69f7 | Fabrice Bellard | s->dct_unquantize(s, block, i, s->qscale); |

648 | 4af7bcc1 | Arpi | ff_idct (block); |

649 | de6d9b64 | Fabrice Bellard | add_pixels_clamped(block, dest, line_size); |

650 | } |
||

651 | } |
||

652 | |||

653 | ```
/* generic function called after a macroblock has been parsed by the
``` |
||

654 | ```
decoder or after it has been encoded by the encoder.
``` |
||

655 | |||

656 | ```
Important variables used:
``` |
||

657 | ```
s->mb_intra : true if intra macroblock
``` |
||

658 | ```
s->mv_dir : motion vector direction
``` |
||

659 | ```
s->mv_type : motion vector type
``` |
||

660 | ```
s->mv : motion vector
``` |
||

661 | ```
s->interlaced_dct : true if interlaced dct used (mpeg2)
``` |
||

662 | ```
*/
``` |
||

663 | void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) |
||

664 | { |
||

665 | ```
int mb_x, mb_y, motion_x, motion_y;
``` |
||

666 | ```
int dct_linesize, dct_offset;
``` |
||

667 | op_pixels_func *op_pix; |
||

668 | |||

669 | mb_x = s->mb_x; |
||

670 | mb_y = s->mb_y; |
||

671 | |||

672 | ```
/* update DC predictors for P macroblocks */
``` |
||

673 | ```
if (!s->mb_intra) {
``` |
||

674 | ```
if (s->h263_pred) {
``` |
||

675 | ```
int wrap, x, y, v;
``` |
||

676 | wrap = 2 * s->mb_width + 2; |
||

677 | ```
v = 1024;
``` |
||

678 | x = 2 * mb_x + 1; |
||

679 | y = 2 * mb_y + 1; |
||

680 | ```
s->dc_val[0][(x) + (y) * wrap] = v;
``` |
||

681 | s->dc_val[0][(x + 1) + (y) * wrap] = v; |
||

682 | s->dc_val[0][(x) + (y + 1) * wrap] = v; |
||

683 | s->dc_val[0][(x + 1) + (y + 1) * wrap] = v; |
||

684 | ```
/* ac pred */
``` |
||

685 | memset(s->ac_val[0][(x) + (y) * wrap], 0, 16 * sizeof(INT16)); |
||

686 | memset(s->ac_val[0][(x + 1) + (y) * wrap], 0, 16 * sizeof(INT16)); |
||

687 | memset(s->ac_val[0][(x) + (y + 1) * wrap], 0, 16 * sizeof(INT16)); |
||

688 | memset(s->ac_val[0][(x + 1) + (y + 1) * wrap], 0, 16 * sizeof(INT16)); |
||

689 | ```
if (s->h263_msmpeg4) {
``` |
||

690 | ```
s->coded_block[(x) + (y) * wrap] = 0;
``` |
||

691 | s->coded_block[(x + 1) + (y) * wrap] = 0; |
||

692 | s->coded_block[(x) + (y + 1) * wrap] = 0; |
||

693 | s->coded_block[(x + 1) + (y + 1) * wrap] = 0; |
||

694 | } |
||

695 | ```
/* chroma */
``` |
||

696 | ```
wrap = s->mb_width + 2;
``` |
||

697 | ```
x = mb_x + 1;
``` |
||

698 | ```
y = mb_y + 1;
``` |
||

699 | ```
s->dc_val[1][(x) + (y) * wrap] = v;
``` |
||

700 | ```
s->dc_val[2][(x) + (y) * wrap] = v;
``` |
||

701 | ```
/* ac pred */
``` |
||

702 | memset(s->ac_val[1][(x) + (y) * wrap], 0, 16 * sizeof(INT16)); |
||

703 | memset(s->ac_val[2][(x) + (y) * wrap], 0, 16 * sizeof(INT16)); |
||

704 | ```
} else {
``` |
||

705 | s->last_dc[0] = 128 << s->intra_dc_precision; |
||

706 | s->last_dc[1] = 128 << s->intra_dc_precision; |
||

707 | s->last_dc[2] = 128 << s->intra_dc_precision; |
||

708 | } |
||

709 | } |
||

710 | |||

711 | ```
/* update motion predictor */
``` |
||

712 | ```
if (s->out_format == FMT_H263) {
``` |
||

713 | ```
int x, y, wrap;
``` |
||

714 | |||

715 | x = 2 * mb_x + 1; |
||

716 | y = 2 * mb_y + 1; |
||

717 | wrap = 2 * s->mb_width + 2; |
||

718 | ```
if (s->mb_intra) {
``` |
||

719 | ```
motion_x = 0;
``` |
||

720 | ```
motion_y = 0;
``` |
||

721 | ```
goto motion_init;
``` |
||

722 | } else if (s->mv_type == MV_TYPE_16X16) { |
||

723 | motion_x = s->mv[0][0][0]; |
||

724 | motion_y = s->mv[0][0][1]; |
||

725 | ```
motion_init:
``` |
||

726 | ```
/* no update if 8X8 because it has been done during parsing */
``` |
||

727 | ```
s->motion_val[(x) + (y) * wrap][0] = motion_x;
``` |
||

728 | ```
s->motion_val[(x) + (y) * wrap][1] = motion_y;
``` |
||

729 | s->motion_val[(x + 1) + (y) * wrap][0] = motion_x; |
||

730 | s->motion_val[(x + 1) + (y) * wrap][1] = motion_y; |
||

731 | s->motion_val[(x) + (y + 1) * wrap][0] = motion_x; |
||

732 | s->motion_val[(x) + (y + 1) * wrap][1] = motion_y; |
||

733 | s->motion_val[(x + 1) + (y + 1) * wrap][0] = motion_x; |
||

734 | s->motion_val[(x + 1) + (y + 1) * wrap][1] = motion_y; |
||

735 | } |
||

736 | } |
||

737 | |||

738 | ```
if (!s->intra_only) {
``` |
||

739 | UINT8 *dest_y, *dest_cb, *dest_cr; |
||

740 | 3bb4e23a | Fabrice Bellard | UINT8 *mbskip_ptr; |

741 | |||

742 | ```
/* avoid copy if macroblock skipped in last frame too */
``` |
||

743 | 21af69f7 | Fabrice Bellard | ```
if (!s->encoding && s->pict_type != B_TYPE) {
``` |

744 | 3bb4e23a | Fabrice Bellard | mbskip_ptr = &s->mbskip_table[s->mb_y * s->mb_width + s->mb_x]; |

745 | ```
if (s->mb_skiped) {
``` |
||

746 | ```
s->mb_skiped = 0;
``` |
||

747 | ```
/* if previous was skipped too, then nothing to do ! */
``` |
||

748 | if (*mbskip_ptr != 0) |
||

749 | ```
goto the_end;
``` |
||

750 | *mbskip_ptr = 1; /* indicate that this time we skiped it */ |
||

751 | ```
} else {
``` |
||

752 | *mbskip_ptr = 0; /* not skipped */ |
||

753 | } |
||

754 | } |
||

755 | de6d9b64 | Fabrice Bellard | |

756 | dest_y = s->current_picture[0] + (mb_y * 16 * s->linesize) + mb_x * 16; |
||

757 | dest_cb = s->current_picture[1] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8; |
||

758 | dest_cr = s->current_picture[2] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8; |
||

759 | |||

760 | ```
if (s->interlaced_dct) {
``` |
||

761 | ```
dct_linesize = s->linesize * 2;
``` |
||

762 | dct_offset = s->linesize; |
||

763 | ```
} else {
``` |
||

764 | dct_linesize = s->linesize; |
||

765 | ```
dct_offset = s->linesize * 8;
``` |
||

766 | } |
||

767 | |||

768 | ```
if (!s->mb_intra) {
``` |
||

769 | ```
/* motion handling */
``` |
||

770 | ```
if (!s->no_rounding)
``` |
||

771 | op_pix = put_pixels_tab; |
||

772 | ```
else
``` |
||

773 | op_pix = put_no_rnd_pixels_tab; |
||

774 | |||

775 | ```
if (s->mv_dir & MV_DIR_FORWARD) {
``` |
||

776 | ```
MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix);
``` |
||

777 | ```
if (!s->no_rounding)
``` |
||

778 | op_pix = avg_pixels_tab; |
||

779 | ```
else
``` |
||

780 | op_pix = avg_no_rnd_pixels_tab; |
||

781 | } |
||

782 | ```
if (s->mv_dir & MV_DIR_BACKWARD) {
``` |
||

783 | ```
MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix);
``` |
||

784 | } |
||

785 | |||

786 | ```
/* add dct residue */
``` |
||

787 | add_dct(s, block[0], 0, dest_y, dct_linesize); |
||

788 | add_dct(s, block[1], 1, dest_y + 8, dct_linesize); |
||

789 | add_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize); |
||

790 | add_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize); |
||

791 | |||

792 | add_dct(s, block[4], 4, dest_cb, dct_linesize >> 1); |
||

793 | add_dct(s, block[5], 5, dest_cr, dct_linesize >> 1); |
||

794 | ```
} else {
``` |
||

795 | ```
/* dct only in intra block */
``` |
||

796 | put_dct(s, block[0], 0, dest_y, dct_linesize); |
||

797 | put_dct(s, block[1], 1, dest_y + 8, dct_linesize); |
||

798 | put_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize); |
||

799 | put_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize); |
||

800 | |||

801 | put_dct(s, block[4], 4, dest_cb, dct_linesize >> 1); |
||

802 | put_dct(s, block[5], 5, dest_cr, dct_linesize >> 1); |
||

803 | } |
||

804 | } |
||

805 | 3bb4e23a | Fabrice Bellard | ```
the_end:
``` |

806 | emms_c(); |
||

807 | de6d9b64 | Fabrice Bellard | } |

808 | |||

809 | static void encode_picture(MpegEncContext *s, int picture_number) |
||

810 | { |
||

811 | ```
int mb_x, mb_y, wrap;
``` |
||

812 | UINT8 *ptr; |
||

813 | ```
int i, motion_x, motion_y;
``` |
||

814 | |||

815 | s->picture_number = picture_number; |
||

816 | ```
if (!s->fixed_qscale)
``` |
||

817 | s->qscale = rate_estimate_qscale(s); |
||

818 | |||

819 | ```
/* precompute matrix */
``` |
||

820 | ```
if (s->out_format == FMT_MJPEG) {
``` |
||

821 | ```
/* for mjpeg, we do include qscale in the matrix */
``` |
||

822 | s->intra_matrix[0] = default_intra_matrix[0]; |
||

823 | for(i=1;i<64;i++) |
||

824 | ```
s->intra_matrix[i] = (default_intra_matrix[i] * s->qscale) >> 3;
``` |
||

825 | ```
convert_matrix(s->q_intra_matrix, s->intra_matrix, 8);
``` |
||

826 | ```
} else {
``` |
||

827 | convert_matrix(s->q_intra_matrix, s->intra_matrix, s->qscale); |
||

828 | convert_matrix(s->q_non_intra_matrix, s->non_intra_matrix, s->qscale); |
||

829 | } |
||

830 | |||

831 | ```
switch(s->out_format) {
``` |
||

832 | ```
case FMT_MJPEG:
``` |
||

833 | mjpeg_picture_header(s); |
||

834 | ```
break;
``` |
||

835 | ```
case FMT_H263:
``` |
||

836 | ```
if (s->h263_msmpeg4)
``` |
||

837 | msmpeg4_encode_picture_header(s, picture_number); |
||

838 | else if (s->h263_pred) |
||

839 | mpeg4_encode_picture_header(s, picture_number); |
||

840 | else if (s->h263_rv10) |
||

841 | rv10_encode_picture_header(s, picture_number); |
||

842 | ```
else
``` |
||

843 | h263_encode_picture_header(s, picture_number); |
||

844 | ```
break;
``` |
||

845 | ```
case FMT_MPEG1:
``` |
||

846 | mpeg1_encode_picture_header(s, picture_number); |
||

847 | ```
break;
``` |
||

848 | } |
||

849 | |||

850 | ```
/* init last dc values */
``` |
||

851 | ```
/* note: quant matrix value (8) is implied here */
``` |
||

852 | s->last_dc[0] = 128; |
||

853 | s->last_dc[1] = 128; |
||

854 | s->last_dc[2] = 128; |
||

855 | ```
s->mb_incr = 1;
``` |
||

856 | s->last_mv[0][0][0] = 0; |
||

857 | s->last_mv[0][0][1] = 0; |
||

858 | s->mv_type = MV_TYPE_16X16; |
||

859 | s->mv_dir = MV_DIR_FORWARD; |
||

860 | |||

861 | for(mb_y=0; mb_y < s->mb_height; mb_y++) { |
||

862 | for(mb_x=0; mb_x < s->mb_width; mb_x++) { |
||

863 | |||

864 | s->mb_x = mb_x; |
||

865 | s->mb_y = mb_y; |
||

866 | |||

867 | ```
/* compute motion vector and macro block type (intra or non intra) */
``` |
||

868 | ```
motion_x = 0;
``` |
||

869 | ```
motion_y = 0;
``` |
||

870 | ```
if (s->pict_type == P_TYPE) {
``` |
||

871 | s->mb_intra = estimate_motion(s, mb_x, mb_y, |
||

872 | &motion_x, |
||

873 | &motion_y); |
||

874 | ```
} else {
``` |
||

875 | ```
s->mb_intra = 1;
``` |
||

876 | } |
||

877 | |||

878 | ```
/* get the pixels */
``` |
||

879 | wrap = s->linesize; |
||

880 | ptr = s->new_picture[0] + (mb_y * 16 * wrap) + mb_x * 16; |
||

881 | 21af69f7 | Fabrice Bellard | ```
get_pixels(s->block[0], ptr, wrap);
``` |

882 | get_pixels(s->block[1], ptr + 8, wrap); |
||

883 | get_pixels(s->block[2], ptr + 8 * wrap, wrap); |
||

884 | get_pixels(s->block[3], ptr + 8 * wrap + 8, wrap); |
||

885 | de6d9b64 | Fabrice Bellard | ```
wrap = s->linesize >> 1;
``` |

886 | ptr = s->new_picture[1] + (mb_y * 8 * wrap) + mb_x * 8; |
||

887 | 21af69f7 | Fabrice Bellard | ```
get_pixels(s->block[4], ptr, wrap);
``` |

888 | de6d9b64 | Fabrice Bellard | |

889 | ```
wrap = s->linesize >> 1;
``` |
||

890 | ptr = s->new_picture[2] + (mb_y * 8 * wrap) + mb_x * 8; |
||

891 | 21af69f7 | Fabrice Bellard | ```
get_pixels(s->block[5], ptr, wrap);
``` |

892 | de6d9b64 | Fabrice Bellard | |

893 | ```
/* subtract previous frame if non intra */
``` |
||

894 | ```
if (!s->mb_intra) {
``` |
||

895 | ```
int dxy, offset, mx, my;
``` |
||

896 | |||

897 | dxy = ((motion_y & 1) << 1) | (motion_x & 1); |
||

898 | ```
ptr = s->last_picture[0] +
``` |
||

899 | ((mb_y * 16 + (motion_y >> 1)) * s->linesize) + |
||

900 | (mb_x * 16 + (motion_x >> 1)); |
||

901 | |||

902 | 21af69f7 | Fabrice Bellard | ```
sub_pixels_2(s->block[0], ptr, s->linesize, dxy);
``` |

903 | sub_pixels_2(s->block[1], ptr + 8, s->linesize, dxy); |
||

904 | sub_pixels_2(s->block[2], ptr + s->linesize * 8, s->linesize, dxy); |
||

905 | sub_pixels_2(s->block[3], ptr + 8 + s->linesize * 8, s->linesize ,dxy); |
||

906 | de6d9b64 | Fabrice Bellard | |

907 | ```
if (s->out_format == FMT_H263) {
``` |
||

908 | ```
/* special rounding for h263 */
``` |
||

909 | ```
dxy = 0;
``` |
||

910 | if ((motion_x & 3) != 0) |
||

911 | ```
dxy |= 1;
``` |
||

912 | if ((motion_y & 3) != 0) |
||

913 | ```
dxy |= 2;
``` |
||

914 | ```
mx = motion_x >> 2;
``` |
||

915 | ```
my = motion_y >> 2;
``` |
||

916 | ```
} else {
``` |
||

917 | ```
mx = motion_x / 2;
``` |
||

918 | ```
my = motion_y / 2;
``` |
||

919 | dxy = ((my & 1) << 1) | (mx & 1); |
||

920 | ```
mx >>= 1;
``` |
||

921 | ```
my >>= 1;
``` |
||

922 | } |
||

923 | offset = ((mb_y * 8 + my) * (s->linesize >> 1)) + (mb_x * 8 + mx); |
||

924 | ```
ptr = s->last_picture[1] + offset;
``` |
||

925 | 21af69f7 | Fabrice Bellard | sub_pixels_2(s->block[4], ptr, s->linesize >> 1, dxy); |

926 | de6d9b64 | Fabrice Bellard | ```
ptr = s->last_picture[2] + offset;
``` |

927 | 21af69f7 | Fabrice Bellard | sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy); |

928 | de6d9b64 | Fabrice Bellard | } |

929 | 3bb4e23a | Fabrice Bellard | emms_c(); |

930 | de6d9b64 | Fabrice Bellard | |

931 | ```
/* DCT & quantize */
``` |
||

932 | ```
if (s->h263_msmpeg4) {
``` |
||

933 | msmpeg4_dc_scale(s); |
||

934 | } else if (s->h263_pred) { |
||

935 | h263_dc_scale(s); |
||

936 | ```
} else {
``` |
||

937 | ```
/* default quantization values */
``` |
||

938 | ```
s->y_dc_scale = 8;
``` |
||

939 | ```
s->c_dc_scale = 8;
``` |
||

940 | } |
||

941 | |||

942 | for(i=0;i<6;i++) { |
||

943 | ```
int last_index;
``` |
||

944 | ```
if (av_fdct == jpeg_fdct_ifast)
``` |
||

945 | 21af69f7 | Fabrice Bellard | last_index = dct_quantize(s, s->block[i], i, s->qscale); |

946 | de6d9b64 | Fabrice Bellard | ```
else
``` |

947 | 21af69f7 | Fabrice Bellard | last_index = dct_quantize_mmx(s, s->block[i], i, s->qscale); |

948 | de6d9b64 | Fabrice Bellard | s->block_last_index[i] = last_index; |

949 | } |
||

950 | |||

951 | ```
/* huffman encode */
``` |
||

952 | ```
switch(s->out_format) {
``` |
||

953 | ```
case FMT_MPEG1:
``` |
||

954 | 21af69f7 | Fabrice Bellard | mpeg1_encode_mb(s, s->block, motion_x, motion_y); |

955 | de6d9b64 | Fabrice Bellard | ```
break;
``` |

956 | ```
case FMT_H263:
``` |
||

957 | ```
if (s->h263_msmpeg4)
``` |
||

958 | 21af69f7 | Fabrice Bellard | msmpeg4_encode_mb(s, s->block, motion_x, motion_y); |

959 | de6d9b64 | Fabrice Bellard | ```
else
``` |

960 | 21af69f7 | Fabrice Bellard | h263_encode_mb(s, s->block, motion_x, motion_y); |

961 | de6d9b64 | Fabrice Bellard | ```
break;
``` |

962 | ```
case FMT_MJPEG:
``` |
||

963 | 21af69f7 | Fabrice Bellard | mjpeg_encode_mb(s, s->block); |

964 | de6d9b64 | Fabrice Bellard | ```
break;
``` |

965 | } |
||

966 | |||

967 | ```
/* decompress blocks so that we keep the state of the decoder */
``` |
||

968 | s->mv[0][0][0] = motion_x; |
||

969 | s->mv[0][0][1] = motion_y; |
||

970 | |||

971 | 21af69f7 | Fabrice Bellard | MPV_decode_mb(s, s->block); |

972 | de6d9b64 | Fabrice Bellard | } |

973 | } |
||

974 | } |
||

975 | |||

976 | static int dct_quantize(MpegEncContext *s, |
||

977 | ```
DCTELEM *block, int n,
``` |
||

978 | ```
int qscale)
``` |
||

979 | { |
||

980 | ```
int i, j, level, last_non_zero, q;
``` |
||

981 | const int *qmat; |
||

982 | |||

983 | av_fdct (block); |
||

984 | |||

985 | ```
if (s->mb_intra) {
``` |
||

986 | if (n < 4) |
||

987 | q = s->y_dc_scale; |
||

988 | ```
else
``` |
||

989 | q = s->c_dc_scale; |
||

990 | ```
q = q << 3;
``` |
||

991 | |||

992 | ```
/* note: block[0] is assumed to be positive */
``` |
||

993 | block[0] = (block[0] + (q >> 1)) / q; |
||

994 | ```
i = 1;
``` |
||

995 | ```
last_non_zero = 0;
``` |
||

996 | ```
if (s->out_format == FMT_H263) {
``` |
||

997 | qmat = s->q_non_intra_matrix; |
||

998 | ```
} else {
``` |
||

999 | qmat = s->q_intra_matrix; |
||

1000 | } |
||

1001 | ```
} else {
``` |
||

1002 | ```
i = 0;
``` |
||

1003 | ```
last_non_zero = -1;
``` |
||

1004 | qmat = s->q_non_intra_matrix; |
||

1005 | } |
||

1006 | |||

1007 | for(;i<64;i++) { |
||

1008 | j = zigzag_direct[i]; |
||

1009 | level = block[j]; |
||

1010 | level = level * qmat[j]; |
||

1011 | ```
#ifdef PARANOID
``` |
||

1012 | { |
||

1013 | static int count = 0; |
||

1014 | ```
int level1, level2, qmat1;
``` |
||

1015 | ```
double val;
``` |
||

1016 | ```
if (qmat == s->q_non_intra_matrix) {
``` |
||

1017 | qmat1 = default_non_intra_matrix[j] * s->qscale; |
||

1018 | ```
} else {
``` |
||

1019 | qmat1 = default_intra_matrix[j] * s->qscale; |
||

1020 | } |
||

1021 | ```
if (av_fdct != jpeg_fdct_ifast)
``` |
||

1022 | val = ((double)block[j] * 8.0) / (double)qmat1; |
||

1023 | ```
else
``` |
||

1024 | val = ((double)block[j] * 8.0 * 2048.0) / |
||

1025 | ```
((double)qmat1 * aanscales[j]);
``` |
||

1026 | ```
level1 = (int)val;
``` |
||

1027 | level2 = level / (1 << (QMAT_SHIFT - 3)); |
||

1028 | ```
if (level1 != level2) {
``` |
||

1029 | ```
fprintf(stderr, "%d: quant error qlevel=%d wanted=%d level=%d qmat1=%d qmat=%d wantedf=%0.6f\n",
``` |
||

1030 | count, level2, level1, block[j], qmat1, qmat[j], |
||

1031 | val); |
||

1032 | count++; |
||

1033 | } |
||

1034 | |||

1035 | } |
||

1036 | ```
#endif
``` |
||

1037 | ```
/* XXX: slight error for the low range. Test should be equivalent to
``` |
||

1038 | ```
(level <= -(1 << (QMAT_SHIFT - 3)) || level >= (1 <<
``` |
||

1039 | ```
(QMAT_SHIFT - 3)))
``` |
||

1040 | ```
*/
``` |
||

1041 | if (((level << (31 - (QMAT_SHIFT - 3))) >> (31 - (QMAT_SHIFT - 3))) != |
||

1042 | level) { |
||

1043 | level = level / (1 << (QMAT_SHIFT - 3)); |
||

1044 | ```
/* XXX: currently, this code is not optimal. the range should be:
``` |
||

1045 | ```
mpeg1: -255..255
``` |
||

1046 | ```
mpeg2: -2048..2047
``` |
||

1047 | ```
h263: -128..127
``` |
||

1048 | ```
mpeg4: -2048..2047
``` |
||

1049 | ```
*/
``` |
||

1050 | if (level > 127) |
||

1051 | ```
level = 127;
``` |
||

1052 | else if (level < -128) |
||

1053 | ```
level = -128;
``` |
||

1054 | block[j] = level; |
||

1055 | last_non_zero = i; |
||

1056 | ```
} else {
``` |
||

1057 | ```
block[j] = 0;
``` |
||

1058 | } |
||

1059 | } |
||

1060 | ```
return last_non_zero;
``` |
||

1061 | } |
||

1062 | |||

1063 | static int dct_quantize_mmx(MpegEncContext *s, |
||

1064 | ```
DCTELEM *block, int n,
``` |
||

1065 | ```
int qscale)
``` |
||

1066 | { |
||

1067 | ```
int i, j, level, last_non_zero, q;
``` |
||

1068 | const int *qmat; |
||

1069 | |||

1070 | av_fdct (block); |
||

1071 | |||

1072 | ```
if (s->mb_intra) {
``` |
||

1073 | if (n < 4) |
||

1074 | q = s->y_dc_scale; |
||

1075 | ```
else
``` |
||

1076 | q = s->c_dc_scale; |
||

1077 | |||

1078 | ```
/* note: block[0] is assumed to be positive */
``` |
||

1079 | block[0] = (block[0] + (q >> 1)) / q; |
||

1080 | ```
i = 1;
``` |
||

1081 | ```
last_non_zero = 0;
``` |
||

1082 | ```
if (s->out_format == FMT_H263) {
``` |
||

1083 | qmat = s->q_non_intra_matrix; |
||

1084 | ```
} else {
``` |
||

1085 | qmat = s->q_intra_matrix; |
||

1086 | } |
||

1087 | ```
} else {
``` |
||

1088 | ```
i = 0;
``` |
||

1089 | ```
last_non_zero = -1;
``` |
||

1090 | qmat = s->q_non_intra_matrix; |
||

1091 | } |
||

1092 | |||

1093 | for(;i<64;i++) { |
||

1094 | j = zigzag_direct[i]; |
||

1095 | level = block[j]; |
||

1096 | level = level * qmat[j]; |
||

1097 | ```
/* XXX: slight error for the low range. Test should be equivalent to
``` |
||

1098 | ```
(level <= -(1 << (QMAT_SHIFT_MMX - 3)) || level >= (1 <<
``` |
||

1099 | ```
(QMAT_SHIFT_MMX - 3)))
``` |
||

1100 | ```
*/
``` |
||

1101 | if (((level << (31 - (QMAT_SHIFT_MMX - 3))) >> (31 - (QMAT_SHIFT_MMX - 3))) != |
||

1102 | level) { |
||

1103 | level = level / (1 << (QMAT_SHIFT_MMX - 3)); |
||

1104 | ```
/* XXX: currently, this code is not optimal. the range should be:
``` |
||

1105 | ```
mpeg1: -255..255
``` |
||

1106 | ```
mpeg2: -2048..2047
``` |
||

1107 | ```
h263: -128..127
``` |
||

1108 | ```
mpeg4: -2048..2047
``` |
||

1109 | ```
*/
``` |
||

1110 | if (level > 127) |
||

1111 | ```
level = 127;
``` |
||

1112 | else if (level < -128) |
||

1113 | ```
level = -128;
``` |
||

1114 | block[j] = level; |
||

1115 | last_non_zero = i; |
||

1116 | ```
} else {
``` |
||

1117 | ```
block[j] = 0;
``` |
||

1118 | } |
||

1119 | } |
||

1120 | ```
return last_non_zero;
``` |
||

1121 | } |
||

1122 | |||

1123 | 21af69f7 | Fabrice Bellard | static void dct_unquantize_mpeg1_c(MpegEncContext *s, |

1124 | DCTELEM *block, int n, int qscale) |
||

1125 | de6d9b64 | Fabrice Bellard | { |

1126 | ```
int i, level;
``` |
||

1127 | ```
const UINT16 *quant_matrix;
``` |
||

1128 | |||

1129 | ```
if (s->mb_intra) {
``` |
||

1130 | if (n < 4) |
||

1131 | block[0] = block[0] * s->y_dc_scale; |
||

1132 | ```
else
``` |
||

1133 | block[0] = block[0] * s->c_dc_scale; |
||

1134 | ```
/* XXX: only mpeg1 */
``` |
||

1135 | quant_matrix = s->intra_matrix; |
||

1136 | for(i=1;i<64;i++) { |
||

1137 | level = block[i]; |
||

1138 | ```
if (level) {
``` |
||

1139 | if (level < 0) { |
||

1140 | level = -level; |
||

1141 | level = (int)(level * qscale * quant_matrix[i]) >> 3; |
||

1142 | level = (level - 1) | 1; |
||

1143 | level = -level; |
||

1144 | ```
} else {
``` |
||

1145 | level = (int)(level * qscale * quant_matrix[i]) >> 3; |
||

1146 | level = (level - 1) | 1; |
||

1147 | } |
||

1148 | ```
#ifdef PARANOID
``` |
||

1149 | if (level < -2048 || level > 2047) |
||

1150 | ```
fprintf(stderr, "unquant error %d %d\n", i, level);
``` |
||

1151 | ```
#endif
``` |
||

1152 | block[i] = level; |
||

1153 | } |
||

1154 | } |
||

1155 | ```
} else {
``` |
||

1156 | ```
i = 0;
``` |
||

1157 | quant_matrix = s->non_intra_matrix; |
||

1158 | for(;i<64;i++) { |
||

1159 | level = block[i]; |
||

1160 | ```
if (level) {
``` |
||

1161 | if (level < 0) { |
||

1162 | level = -level; |
||

1163 | level = (((level << 1) + 1) * qscale * |
||

1164 | ((int) (quant_matrix[i]))) >> 4; |
||

1165 | level = (level - 1) | 1; |
||

1166 | level = -level; |
||

1167 | ```
} else {
``` |
||

1168 | level = (((level << 1) + 1) * qscale * |
||

1169 | ((int) (quant_matrix[i]))) >> 4; |
||

1170 | level = (level - 1) | 1; |
||

1171 | } |
||

1172 | ```
#ifdef PARANOID
``` |
||

1173 | if (level < -2048 || level > 2047) |
||

1174 | ```
fprintf(stderr, "unquant error %d %d\n", i, level);
``` |
||

1175 | ```
#endif
``` |
||

1176 | block[i] = level; |
||

1177 | } |
||

1178 | } |
||

1179 | } |
||

1180 | } |
||

1181 | 21af69f7 | Fabrice Bellard | |

1182 | static void dct_unquantize_h263_c(MpegEncContext *s, |
||

1183 | DCTELEM *block, int n, int qscale) |
||

1184 | { |
||

1185 | ```
int i, level, qmul, qadd;
``` |
||

1186 | |||

1187 | ```
if (s->mb_intra) {
``` |
||

1188 | if (n < 4) |
||

1189 | block[0] = block[0] * s->y_dc_scale; |
||

1190 | ```
else
``` |
||

1191 | block[0] = block[0] * s->c_dc_scale; |
||

1192 | ```
i = 1;
``` |
||

1193 | ```
} else {
``` |
||

1194 | ```
i = 0;
``` |
||

1195 | } |
||

1196 | |||

1197 | ```
qmul = s->qscale << 1;
``` |
||

1198 | qadd = (s->qscale - 1) | 1; |
||

1199 | |||

1200 | for(;i<64;i++) { |
||

1201 | level = block[i]; |
||

1202 | ```
if (level) {
``` |
||

1203 | if (level < 0) { |
||

1204 | level = level * qmul - qadd; |
||

1205 | ```
} else {
``` |
||

1206 | level = level * qmul + qadd; |
||

1207 | } |
||

1208 | ```
#ifdef PARANOID
``` |
||

1209 | if (level < -2048 || level > 2047) |
||

1210 | ```
fprintf(stderr, "unquant error %d %d\n", i, level);
``` |
||

1211 | ```
#endif
``` |
||

1212 | block[i] = level; |
||

1213 | } |
||

1214 | } |
||

1215 | } |
||

1216 | de6d9b64 | Fabrice Bellard | |

1217 | ```
/* rate control */
``` |
||

1218 | |||

1219 | ```
/* an I frame is I_FRAME_SIZE_RATIO bigger than a P frame */
``` |
||

1220 | #define I_FRAME_SIZE_RATIO 3.0 |
||

1221 | #define QSCALE_K 20 |
||

1222 | |||

1223 | static void rate_control_init(MpegEncContext *s) |
||

1224 | { |
||

1225 | ```
s->wanted_bits = 0;
``` |
||

1226 | |||

1227 | ```
if (s->intra_only) {
``` |
||

1228 | s->I_frame_bits = ((INT64)s->bit_rate * FRAME_RATE_BASE) / s->frame_rate; |
||

1229 | s->P_frame_bits = s->I_frame_bits; |
||

1230 | ```
} else {
``` |
||

1231 | s->P_frame_bits = (int) ((float)(s->gop_size * s->bit_rate) / |
||

1232 | (float)((float)s->frame_rate / FRAME_RATE_BASE * (I_FRAME_SIZE_RATIO + s->gop_size - 1))); |
||

1233 | ```
s->I_frame_bits = (int)(s->P_frame_bits * I_FRAME_SIZE_RATIO);
``` |
||

1234 | } |
||

1235 | |||

1236 | ```
#if defined(DEBUG)
``` |
||

1237 | ```
printf("I_frame_size=%d P_frame_size=%d\n",
``` |
||

1238 | s->I_frame_bits, s->P_frame_bits); |
||

1239 | ```
#endif
``` |
||

1240 | } |
||

1241 | |||

1242 | |||

1243 | ```
/*
``` |
||

1244 | ```
* This heuristic is rather poor, but at least we do not have to
``` |
||

1245 | ```
* change the qscale at every macroblock.
``` |
||

1246 | ```
*/
``` |
||

1247 | static int rate_estimate_qscale(MpegEncContext *s) |
||

1248 | { |
||

1249 | long long total_bits = s->total_bits; |
||

1250 | ```
float q;
``` |
||

1251 | ```
int qscale, diff, qmin;
``` |
||

1252 | |||

1253 | ```
if (s->pict_type == I_TYPE) {
``` |
||

1254 | s->wanted_bits += s->I_frame_bits; |
||

1255 | ```
} else {
``` |
||

1256 | s->wanted_bits += s->P_frame_bits; |
||

1257 | } |
||

1258 | diff = s->wanted_bits - total_bits; |
||

1259 | q = 31.0 - (float)diff / (QSCALE_K * s->mb_height * s->mb_width); |
||

1260 | ```
/* adjust for I frame */
``` |
||

1261 | ```
if (s->pict_type == I_TYPE && !s->intra_only) {
``` |
||

1262 | q /= I_FRAME_SIZE_RATIO; |
||

1263 | } |
||

1264 | |||

1265 | ```
/* using a too small Q scale leeds to problems in mpeg1 and h263
``` |
||

1266 | ```
because AC coefficients are clamped to 255 or 127 */
``` |
||

1267 | ```
qmin = 3;
``` |
||

1268 | ```
if (q < qmin)
``` |
||

1269 | q = qmin; |
||

1270 | else if (q > 31) |
||

1271 | ```
q = 31;
``` |
||

1272 | qscale = (int)(q + 0.5); |
||

1273 | ```
#if defined(DEBUG)
``` |
||

1274 | ```
printf("%d: total=%Ld br=%0.1f diff=%d qest=%0.1f\n",
``` |
||

1275 | s->picture_number, |
||

1276 | total_bits, |
||

1277 | ```
(float)s->frame_rate / FRAME_RATE_BASE *
``` |
||

1278 | total_bits / s->picture_number, |
||

1279 | diff, q); |
||

1280 | ```
#endif
``` |
||

1281 | ```
return qscale;
``` |
||

1282 | } |
||

1283 | |||

1284 | AVCodec mpeg1video_encoder = { |
||

1285 | ```
"mpeg1video",
``` |
||

1286 | CODEC_TYPE_VIDEO, |
||

1287 | CODEC_ID_MPEG1VIDEO, |
||

1288 | ```
sizeof(MpegEncContext),
``` |
||

1289 | MPV_encode_init, |
||

1290 | MPV_encode_picture, |
||

1291 | MPV_encode_end, |
||

1292 | }; |
||

1293 | |||

1294 | AVCodec h263_encoder = { |
||

1295 | ```
"h263",
``` |
||

1296 | CODEC_TYPE_VIDEO, |
||

1297 | CODEC_ID_H263, |
||

1298 | ```
sizeof(MpegEncContext),
``` |
||

1299 | MPV_encode_init, |
||

1300 | MPV_encode_picture, |
||

1301 | MPV_encode_end, |
||

1302 | }; |
||

1303 | |||

1304 | AVCodec h263p_encoder = { |
||

1305 | ```
"h263p",
``` |
||

1306 | CODEC_TYPE_VIDEO, |
||

1307 | CODEC_ID_H263P, |
||

1308 | ```
sizeof(MpegEncContext),
``` |
||

1309 | MPV_encode_init, |
||

1310 | MPV_encode_picture, |
||

1311 | MPV_encode_end, |
||

1312 | }; |
||

1313 | |||

1314 | AVCodec rv10_encoder = { |
||

1315 | ```
"rv10",
``` |
||

1316 | CODEC_TYPE_VIDEO, |
||

1317 | CODEC_ID_RV10, |
||

1318 | ```
sizeof(MpegEncContext),
``` |
||

1319 | MPV_encode_init, |
||

1320 | MPV_encode_picture, |
||

1321 | MPV_encode_end, |
||

1322 | }; |
||

1323 | |||

1324 | AVCodec mjpeg_encoder = { |
||

1325 | ```
"mjpeg",
``` |
||

1326 | CODEC_TYPE_VIDEO, |
||

1327 | CODEC_ID_MJPEG, |
||

1328 | ```
sizeof(MpegEncContext),
``` |
||

1329 | MPV_encode_init, |
||

1330 | MPV_encode_picture, |
||

1331 | MPV_encode_end, |
||

1332 | }; |
||

1333 | |||

1334 | AVCodec opendivx_encoder = { |
||

1335 | ```
"opendivx",
``` |
||

1336 | CODEC_TYPE_VIDEO, |
||

1337 | CODEC_ID_OPENDIVX, |
||

1338 | ```
sizeof(MpegEncContext),
``` |
||

1339 | MPV_encode_init, |
||

1340 | MPV_encode_picture, |
||

1341 | MPV_encode_end, |
||

1342 | }; |
||

1343 | |||

1344 | AVCodec msmpeg4_encoder = { |
||

1345 | ```
"msmpeg4",
``` |
||

1346 | CODEC_TYPE_VIDEO, |
||

1347 | CODEC_ID_MSMPEG4, |
||

1348 | ```
sizeof(MpegEncContext),
``` |
||

1349 | MPV_encode_init, |
||

1350 | MPV_encode_picture, |
||

1351 | MPV_encode_end, |
||

1352 | }; |