FFmpeg
h263.c
Go to the documentation of this file.
1 /*
2  * H.263/MPEG-4 backend for encoder and decoder
3  * Copyright (c) 2000,2001 Fabrice Bellard
4  * H.263+ support.
5  * Copyright (c) 2001 Juan J. Sierralta P
6  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
7  *
8  * This file is part of FFmpeg.
9  *
10  * FFmpeg is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * FFmpeg is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with FFmpeg; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 /**
26  * @file
27  * H.263/MPEG-4 codec.
28  */
29 
30 #include "libavutil/thread.h"
31 #include "mpegvideo.h"
32 #include "h263.h"
33 #include "h263data.h"
34 #include "h263dsp.h"
35 #include "idctdsp.h"
36 #include "mathops.h"
37 #include "mpegpicture.h"
38 #include "mpegutils.h"
39 #include "rl.h"
40 
41 static av_cold void h263_init_rl_inter(void)
42 {
43  static uint8_t h263_rl_inter_table[2][2 * MAX_RUN + MAX_LEVEL + 3];
44  ff_rl_init(&ff_h263_rl_inter, h263_rl_inter_table);
45 }
46 
48 {
49  static AVOnce init_static_once = AV_ONCE_INIT;
50  ff_thread_once(&init_static_once, h263_init_rl_inter);
51 }
52 
54  const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
55  //FIXME a lot of that is only needed for !low_delay
56  const int wrap = s->b8_stride;
57  const int xy = s->block_index[0];
58 
59  if(s->mv_type != MV_TYPE_8X8){
60  int motion_x, motion_y;
61  if (s->mb_intra) {
62  motion_x = 0;
63  motion_y = 0;
64  } else if (s->mv_type == MV_TYPE_16X16) {
65  motion_x = s->mv[0][0][0];
66  motion_y = s->mv[0][0][1];
67  } else /*if (s->mv_type == MV_TYPE_FIELD)*/ {
68  int i;
69  motion_x = s->mv[0][0][0] + s->mv[0][1][0];
70  motion_y = s->mv[0][0][1] + s->mv[0][1][1];
71  motion_x = (motion_x>>1) | (motion_x&1);
72  for(i=0; i<2; i++){
73  s->p_field_mv_table[i][0][mb_xy][0]= s->mv[0][i][0];
74  s->p_field_mv_table[i][0][mb_xy][1]= s->mv[0][i][1];
75  }
76  s->cur_pic.ref_index[0][4*mb_xy ] =
77  s->cur_pic.ref_index[0][4*mb_xy + 1] = s->field_select[0][0];
78  s->cur_pic.ref_index[0][4*mb_xy + 2] =
79  s->cur_pic.ref_index[0][4*mb_xy + 3] = s->field_select[0][1];
80  }
81 
82  /* no update if 8X8 because it has been done during parsing */
83  s->cur_pic.motion_val[0][xy][0] = motion_x;
84  s->cur_pic.motion_val[0][xy][1] = motion_y;
85  s->cur_pic.motion_val[0][xy + 1][0] = motion_x;
86  s->cur_pic.motion_val[0][xy + 1][1] = motion_y;
87  s->cur_pic.motion_val[0][xy + wrap][0] = motion_x;
88  s->cur_pic.motion_val[0][xy + wrap][1] = motion_y;
89  s->cur_pic.motion_val[0][xy + 1 + wrap][0] = motion_x;
90  s->cur_pic.motion_val[0][xy + 1 + wrap][1] = motion_y;
91  }
92 }
93 
95  int qp_c;
96  const int linesize = s->linesize;
97  const int uvlinesize= s->uvlinesize;
98  const int xy = s->mb_y * s->mb_stride + s->mb_x;
99  uint8_t *dest_y = s->dest[0];
100  uint8_t *dest_cb= s->dest[1];
101  uint8_t *dest_cr= s->dest[2];
102 
103  /*
104  Diag Top
105  Left Center
106  */
107  if (!IS_SKIP(s->cur_pic.mb_type[xy])) {
108  qp_c= s->qscale;
109  s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize, linesize, qp_c);
110  s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c);
111  }else
112  qp_c= 0;
113 
114  if(s->mb_y){
115  int qp_dt, qp_tt, qp_tc;
116 
117  if (IS_SKIP(s->cur_pic.mb_type[xy - s->mb_stride]))
118  qp_tt=0;
119  else
120  qp_tt = s->cur_pic.qscale_table[xy - s->mb_stride];
121 
122  if(qp_c)
123  qp_tc= qp_c;
124  else
125  qp_tc= qp_tt;
126 
127  if(qp_tc){
128  const int chroma_qp= s->chroma_qscale_table[qp_tc];
129  s->h263dsp.h263_v_loop_filter(dest_y, linesize, qp_tc);
130  s->h263dsp.h263_v_loop_filter(dest_y + 8, linesize, qp_tc);
131 
132  s->h263dsp.h263_v_loop_filter(dest_cb, uvlinesize, chroma_qp);
133  s->h263dsp.h263_v_loop_filter(dest_cr, uvlinesize, chroma_qp);
134  }
135 
136  if(qp_tt)
137  s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize + 8, linesize, qp_tt);
138 
139  if(s->mb_x){
140  if (qp_tt || IS_SKIP(s->cur_pic.mb_type[xy - 1 - s->mb_stride]))
141  qp_dt= qp_tt;
142  else
143  qp_dt = s->cur_pic.qscale_table[xy - 1 - s->mb_stride];
144 
145  if(qp_dt){
146  const int chroma_qp= s->chroma_qscale_table[qp_dt];
147  s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize, linesize, qp_dt);
148  s->h263dsp.h263_h_loop_filter(dest_cb - 8 * uvlinesize, uvlinesize, chroma_qp);
149  s->h263dsp.h263_h_loop_filter(dest_cr - 8 * uvlinesize, uvlinesize, chroma_qp);
150  }
151  }
152  }
153 
154  if(qp_c){
155  s->h263dsp.h263_h_loop_filter(dest_y + 8, linesize, qp_c);
156  if(s->mb_y + 1 == s->mb_height)
157  s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c);
158  }
159 
160  if(s->mb_x){
161  int qp_lc;
162  if (qp_c || IS_SKIP(s->cur_pic.mb_type[xy - 1]))
163  qp_lc= qp_c;
164  else
165  qp_lc = s->cur_pic.qscale_table[xy - 1];
166 
167  if(qp_lc){
168  s->h263dsp.h263_h_loop_filter(dest_y, linesize, qp_lc);
169  if(s->mb_y + 1 == s->mb_height){
170  const int chroma_qp= s->chroma_qscale_table[qp_lc];
171  s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize, linesize, qp_lc);
172  s->h263dsp.h263_h_loop_filter(dest_cb, uvlinesize, chroma_qp);
173  s->h263dsp.h263_h_loop_filter(dest_cr, uvlinesize, chroma_qp);
174  }
175  }
176  }
177 }
178 
179 int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir,
180  int *px, int *py)
181 {
182  int wrap;
183  int16_t *A, *B, *C, (*mot_val)[2];
184  static const int off[4]= {2, 1, 1, -1};
185 
186  wrap = s->b8_stride;
187  mot_val = s->cur_pic.motion_val[dir] + s->block_index[block];
188 
189  A = mot_val[ - 1];
190  /* special case for first (slice) line */
191  if (s->first_slice_line && block<3) {
192  // we can't just change some MVs to simulate that as we need them for the B-frames (and ME)
193  // and if we ever support non rectangular objects than we need to do a few ifs here anyway :(
194  if(block==0){ //most common case
195  if(s->mb_x == s->resync_mb_x){ //rare
196  *px= *py = 0;
197  }else if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare
198  C = mot_val[off[block] - wrap];
199  if(s->mb_x==0){
200  *px = C[0];
201  *py = C[1];
202  }else{
203  *px = mid_pred(A[0], 0, C[0]);
204  *py = mid_pred(A[1], 0, C[1]);
205  }
206  }else{
207  *px = A[0];
208  *py = A[1];
209  }
210  }else if(block==1){
211  if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare
212  C = mot_val[off[block] - wrap];
213  *px = mid_pred(A[0], 0, C[0]);
214  *py = mid_pred(A[1], 0, C[1]);
215  }else{
216  *px = A[0];
217  *py = A[1];
218  }
219  }else{ /* block==2*/
220  B = mot_val[ - wrap];
221  C = mot_val[off[block] - wrap];
222  if(s->mb_x == s->resync_mb_x) //rare
223  A[0]=A[1]=0;
224 
225  *px = mid_pred(A[0], B[0], C[0]);
226  *py = mid_pred(A[1], B[1], C[1]);
227  }
228  } else {
229  B = mot_val[ - wrap];
230  C = mot_val[off[block] - wrap];
231  *px = mid_pred(A[0], B[0], C[0]);
232  *py = mid_pred(A[1], B[1], C[1]);
233  }
234  return *mot_val;
235 }
A
#define A(x)
Definition: vpx_arith.h:28
MV_TYPE_16X16
#define MV_TYPE_16X16
1 vector for the whole mb
Definition: mpegvideo.h:265
h263data.h
thread.h
MAX_RUN
#define MAX_RUN
Definition: rl.h:35
h263dsp.h
mpegvideo.h
mpegutils.h
ff_h263_pred_motion
int16_t * ff_h263_pred_motion(MpegEncContext *s, int block, int dir, int *px, int *py)
Definition: h263.c:179
wrap
#define wrap(func)
Definition: neontest.h:65
h263_init_rl_inter
static av_cold void h263_init_rl_inter(void)
Definition: h263.c:41
ff_h263_update_motion_val
void ff_h263_update_motion_val(MpegEncContext *s)
Definition: h263.c:53
C
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
Definition: writing_filters.txt:58
ff_thread_once
static int ff_thread_once(char *control, void(*routine)(void))
Definition: thread.h:205
av_cold
#define av_cold
Definition: attributes.h:90
s
#define s(width, name)
Definition: cbs_vp9.c:198
B
#define B
Definition: huffyuv.h:42
IS_SKIP
#define IS_SKIP(a)
Definition: mpegutils.h:76
ff_rl_init
av_cold void ff_rl_init(RLTable *rl, uint8_t static_store[2][2 *MAX_RUN+MAX_LEVEL+3])
Initialize index_run, max_level and max_run from n, last, table_vlc, table_run and table_level.
Definition: rl.c:44
AV_ONCE_INIT
#define AV_ONCE_INIT
Definition: thread.h:203
mathops.h
AVOnce
#define AVOnce
Definition: thread.h:202
MV_TYPE_8X8
#define MV_TYPE_8X8
4 vectors (H.263, MPEG-4 4MV)
Definition: mpegvideo.h:266
MAX_LEVEL
#define MAX_LEVEL
Definition: rl.h:36
ff_h263_rl_inter
RLTable ff_h263_rl_inter
Definition: h263data.c:159
mpegpicture.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
idctdsp.h
mid_pred
#define mid_pred
Definition: mathops.h:96
ff_h263_loop_filter
void ff_h263_loop_filter(MpegEncContext *s)
Definition: h263.c:94
rl.h
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
ff_h263_init_rl_inter
av_cold void ff_h263_init_rl_inter(void)
Definition: h263.c:47
MpegEncContext
MpegEncContext.
Definition: mpegvideo.h:73
h263.h