| rev |
line source |
|
nengel@2
|
1 /*
|
|
nengel@2
|
2 * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
|
|
nengel@2
|
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
|
nengel@2
|
4 *
|
|
nengel@2
|
5 * This file is part of FFmpeg.
|
|
nengel@2
|
6 *
|
|
nengel@2
|
7 * FFmpeg is free software; you can redistribute it and/or
|
|
nengel@2
|
8 * modify it under the terms of the GNU Lesser General Public
|
|
nengel@2
|
9 * License as published by the Free Software Foundation; either
|
|
nengel@2
|
10 * version 2.1 of the License, or (at your option) any later version.
|
|
nengel@2
|
11 *
|
|
nengel@2
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
|
nengel@2
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
nengel@2
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
nengel@2
|
15 * Lesser General Public License for more details.
|
|
nengel@2
|
16 *
|
|
nengel@2
|
17 * You should have received a copy of the GNU Lesser General Public
|
|
nengel@2
|
18 * License along with FFmpeg; if not, write to the Free Software
|
|
nengel@2
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
nengel@2
|
20 */
|
|
nengel@2
|
21 #include "h264_types.h"
|
|
nengel@2
|
22 #include "h264_parser.h"
|
|
nengel@2
|
23 #include "h264_nal.h"
|
|
nengel@2
|
24 #include "h264_entropy.h"
|
|
nengel@2
|
25 #include "h264_rec.h"
|
|
nengel@2
|
26 #include "h264_pred_mode.h"
|
|
nengel@2
|
27 #include "h264_misc.h"
|
|
nengel@2
|
28 // #undef NDEBUG
|
|
nengel@2
|
29 #include <assert.h>
|
|
nengel@2
|
30
|
|
nengel@2
|
31 static int decode_slice_entropy_seq(H264Context *h, EntropyContext *ec, H264Slice *s, GetBitContext *gb, H264Mb *mbs){
|
|
nengel@2
|
32 int i,j;
|
|
nengel@2
|
33 // GetBitContext *gb = s->gb;
|
|
nengel@2
|
34 CABACContext *c = &ec->c;
|
|
nengel@2
|
35
|
|
nengel@2
|
36 if( !s->pps.cabac ){
|
|
nengel@2
|
37 av_log(AV_LOG_ERROR, "Only cabac encoded streams are supported\n");
|
|
nengel@2
|
38 return -1;
|
|
nengel@2
|
39 }
|
|
nengel@2
|
40
|
|
nengel@2
|
41 init_dequant_tables(s, ec);
|
|
nengel@2
|
42 ec->curr_qscale = s->qscale;
|
|
nengel@2
|
43 ec->last_qscale_diff = 0;
|
|
nengel@2
|
44 ec->chroma_qp[0] = get_chroma_qp((H264Slice *) s, 0, s->qscale);
|
|
nengel@2
|
45 ec->chroma_qp[1] = get_chroma_qp((H264Slice *) s, 1, s->qscale);
|
|
nengel@2
|
46
|
|
nengel@2
|
47 /* realign */
|
|
nengel@2
|
48 align_get_bits( gb );
|
|
nengel@2
|
49 /* init cabac */
|
|
nengel@2
|
50 ff_init_cabac_decoder( c, gb->buffer + get_bits_count(gb)/8, (get_bits_left(gb) + 7)/8);
|
|
nengel@2
|
51
|
|
nengel@2
|
52 ff_h264_init_cabac_states(ec, s, c);
|
|
nengel@2
|
53
|
|
nengel@2
|
54 for(j=0; j<ec->mb_height; j++){
|
|
nengel@2
|
55 init_entropy_buf(ec, s, j);
|
|
nengel@2
|
56 for(i=0; i<ec->mb_width; i++){
|
|
nengel@2
|
57 int eos,ret;
|
|
nengel@2
|
58 H264Mb *m = &mbs[i + j*ec->mb_width];
|
|
nengel@2
|
59 //memset(m, 0, sizeof(H264Mb));
|
|
nengel@2
|
60 m->mb_x=i;
|
|
nengel@2
|
61 m->mb_y=j;
|
|
nengel@2
|
62 ec->m = m;
|
|
nengel@2
|
63
|
|
nengel@2
|
64 ret = ff_h264_decode_mb_cabac(ec, s, c);
|
|
nengel@2
|
65 eos = get_cabac_terminate( c);
|
|
nengel@2
|
66 (void) eos;
|
|
nengel@2
|
67 if( ret < 0 || c->bytestream > c->bytestream_end + 2) {
|
|
nengel@2
|
68 av_log(AV_LOG_ERROR, "error while decoding MB %d %d, bytestream (%td)\n", m->mb_x, m->mb_y, c->bytestream_end - c->bytestream);
|
|
nengel@2
|
69 return -1;
|
|
nengel@2
|
70 }
|
|
nengel@2
|
71 }
|
|
nengel@2
|
72 }
|
|
nengel@2
|
73
|
|
nengel@2
|
74 // av_freep(&s->gb.raw);
|
|
nengel@2
|
75 // if (s->gb.rbsp)
|
|
nengel@2
|
76 // av_freep(&s->gb.rbsp);
|
|
nengel@2
|
77
|
|
nengel@2
|
78 return 0;
|
|
nengel@2
|
79 }
|
|
nengel@2
|
80
|
|
nengel@2
|
81
|
|
nengel@2
|
82
|
|
nengel@2
|
83 /**
|
|
nengel@2
|
84 * Sequential version
|
|
nengel@2
|
85 */
|
|
nengel@2
|
86 static void decode_slice_mb_seq(H264Context *h, MBRecContext *d, H264Slice *s2, H264Mb *mbs){
|
|
nengel@2
|
87
|
|
nengel@2
|
88 for (int i=0; i<2; i++){
|
|
nengel@2
|
89 for(int j=0; j< s2->ref_count[i]; j++){
|
|
nengel@2
|
90 if (s2->ref_list_cpn[i][j] ==-1)
|
|
nengel@2
|
91 continue;
|
|
nengel@2
|
92 int k;
|
|
nengel@2
|
93 for (k=0; k<h->max_dpb_cnt; k++){
|
|
nengel@2
|
94 if(h->dpb[k].reference >= 2 && h->dpb[k].cpn == s2->ref_list_cpn[i][j]){
|
|
nengel@2
|
95 s2->dp_ref_list[i][j] = &h->dpb[k];
|
|
nengel@2
|
96 break;
|
|
nengel@2
|
97 }
|
|
nengel@2
|
98 }
|
|
nengel@2
|
99 }
|
|
nengel@2
|
100 }
|
|
nengel@2
|
101
|
|
nengel@2
|
102 get_dpb_entry(h, s2);
|
|
nengel@2
|
103
|
|
nengel@2
|
104 if (!h->no_mbd){
|
|
nengel@2
|
105 for(int j=0; j<d->mb_height; j++){
|
|
nengel@2
|
106 init_mbrec_context(d, d->mrs, s2, j);
|
|
nengel@2
|
107 if (h->profile) printf("\n[MBREC LINE %d ", j);
|
|
nengel@2
|
108 for(int i=0; i<d->mb_width; i++){
|
|
nengel@2
|
109
|
|
nengel@2
|
110 if ((i & 0x7) == 0) start_timer(h, REC);
|
|
nengel@2
|
111 H264Mb *m = &mbs[i + j*d->mb_width];
|
|
nengel@2
|
112 if (h->profile==2)
|
|
nengel@2
|
113 pred_motion_mb_rec (d, d->mrs, s2, m);
|
|
nengel@2
|
114 else{
|
|
nengel@2
|
115 h264_decode_mb_internal(d, d->mrs, s2, m);
|
|
nengel@2
|
116 }
|
|
nengel@2
|
117 stop_timer(h, REC);
|
|
nengel@2
|
118 }
|
|
nengel@2
|
119 draw_edges(d, s2, j);
|
|
nengel@2
|
120
|
|
nengel@2
|
121 }
|
|
nengel@2
|
122 }
|
|
nengel@2
|
123
|
|
nengel@2
|
124 for (int i=0; i<s2->release_cnt; i++){
|
|
nengel@2
|
125 for(int j=0; j<h->max_dpb_cnt; j++){
|
|
nengel@2
|
126 if(h->dpb[j].cpn== s2->release_ref_cpn[i]){
|
|
nengel@2
|
127 release_dpb_entry(h, &h->dpb[j], 2);
|
|
nengel@2
|
128 break;
|
|
nengel@2
|
129 }
|
|
nengel@2
|
130 }
|
|
nengel@2
|
131 }
|
|
nengel@2
|
132 s2->release_cnt=0;
|
|
nengel@2
|
133 }
|
|
nengel@2
|
134
|
|
nengel@2
|
135 /*
|
|
nengel@2
|
136 * The following code is the main loop of the file converter
|
|
nengel@2
|
137 */
|
|
nengel@2
|
138 int h264_decode_seq( H264Context *h) {
|
|
nengel@2
|
139 ParserContext *pc;
|
|
nengel@2
|
140 NalContext *nc;
|
|
nengel@2
|
141 EntropyContext *ec;
|
|
nengel@2
|
142 MBRecContext *rc;
|
|
nengel@2
|
143 OutputContext *oc;
|
|
nengel@2
|
144
|
|
nengel@2
|
145 H264Slice slice, *s=&slice;
|
|
nengel@2
|
146 H264Mb *mbs;
|
|
nengel@2
|
147 DecodedPicture *out;
|
|
nengel@2
|
148 int frames=0;
|
|
nengel@2
|
149
|
|
nengel@2
|
150 #if HAVE_LIBSDL2
|
|
nengel@2
|
151 pthread_t sdl_thr;
|
|
nengel@2
|
152 if (h->display){
|
|
nengel@2
|
153 pthread_create(&sdl_thr, NULL, sdl_thread, h);
|
|
nengel@2
|
154 }
|
|
nengel@2
|
155 #endif
|
|
nengel@2
|
156
|
|
nengel@2
|
157 pc = get_parse_context(h->ifile);
|
|
nengel@2
|
158 nc = get_nal_context(h->width, h->height);
|
|
nengel@2
|
159
|
|
nengel@2
|
160 memset(s, 0, sizeof(H264Slice));
|
|
nengel@2
|
161 mbs = av_malloc( h->mb_height * h->mb_width * sizeof(H264Mb));
|
|
nengel@2
|
162
|
|
nengel@2
|
163 ec = get_entropy_context( h );
|
|
nengel@2
|
164 rc = get_mbrec_context(h);
|
|
nengel@2
|
165 rc->top_next = rc->top = av_malloc( h->mb_width * sizeof(TopBorder));
|
|
nengel@2
|
166
|
|
nengel@2
|
167 oc = get_output_context( h );
|
|
nengel@2
|
168
|
|
nengel@2
|
169 av_start_timer();
|
|
nengel@2
|
170 GetBitContext gb = {0,};
|
|
nengel@2
|
171 while(!pc->final_frame && frames++ < h->num_frames && !h->quit){
|
|
nengel@2
|
172 if (h->profile) start_timer(h, FRONT);
|
|
nengel@2
|
173 av_read_frame_internal(pc, &gb);
|
|
nengel@2
|
174 decode_nal_units(nc, s, &gb);
|
|
nengel@2
|
175 if (h->profile) stop_timer(h, FRONT);
|
|
nengel@2
|
176 // memset(s->mbs, 0, sizeof(H264Mb)*ec->mb_width*ec->mb_height);
|
|
nengel@2
|
177 if (h->profile) start_timer(h, ED);
|
|
nengel@2
|
178 decode_slice_entropy_seq(h, ec, s, &gb, mbs);
|
|
nengel@2
|
179 if (h->profile) stop_timer(h, ED);
|
|
nengel@2
|
180
|
|
nengel@2
|
181 if (h->profile) start_timer(h, REC);
|
|
nengel@2
|
182 decode_slice_mb_seq(h, rc, s, mbs);
|
|
nengel@2
|
183 if (h->profile) stop_timer(h, REC);
|
|
nengel@2
|
184
|
|
nengel@2
|
185 out =output_frame(h, oc, s->curr_pic, h->ofile, h->frame_width, h->frame_height);
|
|
nengel@2
|
186 if (out){
|
|
nengel@2
|
187 release_dpb_entry(h, out, 1);
|
|
nengel@2
|
188 }
|
|
nengel@2
|
189
|
|
nengel@2
|
190 print_report(oc->frame_number, oc->video_size, 0, h->verbose);
|
|
nengel@2
|
191 if (h->profile == 3){
|
|
nengel@2
|
192 printf("[ENTROPY %.3fms] [MBREC %.3fms]\n", h->last_time[ED] , h->last_time[REC]);
|
|
nengel@2
|
193 }
|
|
nengel@2
|
194 }
|
|
nengel@2
|
195 while ((out=output_frame(h, oc, NULL, h->ofile, h->frame_width, h->frame_height))) ;
|
|
nengel@2
|
196
|
|
nengel@2
|
197 print_report(oc->frame_number, oc->video_size, 1, h->verbose);
|
|
nengel@2
|
198 h->num_frames = oc->frame_number;
|
|
nengel@2
|
199 /* finished ! */
|
|
nengel@2
|
200 av_freep(&mbs);
|
|
nengel@2
|
201 av_freep(&gb.raw);
|
|
nengel@2
|
202 if (gb.rbsp)
|
|
nengel@2
|
203 av_freep(&gb.rbsp);
|
|
nengel@2
|
204 av_freep(&rc->top);
|
|
nengel@2
|
205
|
|
nengel@2
|
206 free_parse_context(pc);
|
|
nengel@2
|
207 free_nal_context (nc);
|
|
nengel@2
|
208 free_entropy_context(ec);
|
|
nengel@2
|
209 free_mbrec_context(rc);
|
|
nengel@2
|
210 free_output_context(oc);
|
|
nengel@2
|
211
|
|
nengel@2
|
212 #if HAVE_LIBSDL2
|
|
nengel@2
|
213 if (h->display){
|
|
nengel@2
|
214 signal_sdl_exit(h);
|
|
nengel@2
|
215 pthread_join(sdl_thr, NULL);
|
|
nengel@2
|
216 }
|
|
nengel@2
|
217 #endif
|
|
nengel@2
|
218
|
|
nengel@2
|
219 return 0;
|
|
nengel@2
|
220 }
|