Mercurial > libavcodec.hg
annotate libdiracdec.c @ 8991:ca768cb2bfb6 libavcodec
Use last decoded SPS as current SPS in order to parse picture timing SEI
correctly. This works around an apparent H.264 standard deficiency.
Patch by Ivan Schreter, schreter gmx net
author | cehoyos |
---|---|
date | Fri, 20 Feb 2009 16:20:01 +0000 |
parents | e9d9d946f213 |
children | 043574c5c153 |
rev | line source |
---|---|
6734 | 1 /* |
2 * Dirac decoder support via libdirac library | |
3 * Copyright (c) 2005 BBC, Andrew Kennedy <dirac at rd dot bbc dot co dot uk> | |
4 * Copyright (c) 2006-2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com > | |
5 * | |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
23 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8422
diff
changeset
|
24 * @file libavcodec/libdiracdec.c |
6734 | 25 * Dirac decoder support via libdirac library; more details about the Dirac |
26 * project can be found at http://dirac.sourceforge.net/. | |
27 * The libdirac_decoder library implements Dirac specification version 2.2 | |
28 * (http://dirac.sourceforge.net/specification.html). | |
29 */ | |
30 | |
31 #include "libdirac.h" | |
32 | |
33 #undef NDEBUG | |
34 #include <assert.h> | |
35 | |
36 #include <libdirac_decoder/dirac_parser.h> | |
37 | |
38 /** contains a single frame returned from Dirac */ | |
39 typedef struct FfmpegDiracDecoderParams | |
40 { | |
41 /** decoder handle */ | |
42 dirac_decoder_t* p_decoder; | |
43 | |
44 /** buffer to hold decoded frame */ | |
45 unsigned char* p_out_frame_buf; | |
46 } FfmpegDiracDecoderParams; | |
47 | |
48 | |
49 /** | |
50 * returns FFmpeg chroma format | |
51 */ | |
52 static enum PixelFormat GetFfmpegChromaFormat(dirac_chroma_t dirac_pix_fmt) | |
53 { | |
54 int num_formats = sizeof(ffmpeg_dirac_pixel_format_map) / | |
55 sizeof(ffmpeg_dirac_pixel_format_map[0]); | |
56 int idx; | |
57 | |
58 for (idx = 0; idx < num_formats; ++idx) { | |
59 if (ffmpeg_dirac_pixel_format_map[idx].dirac_pix_fmt == dirac_pix_fmt) { | |
60 return ffmpeg_dirac_pixel_format_map[idx].ff_pix_fmt; | |
61 } | |
62 } | |
63 return PIX_FMT_NONE; | |
64 } | |
65 | |
66 static int libdirac_decode_init(AVCodecContext *avccontext) | |
67 { | |
68 | |
69 FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data ; | |
70 p_dirac_params->p_decoder = dirac_decoder_init(avccontext->debug); | |
71 | |
72 if (!p_dirac_params->p_decoder) | |
73 return -1; | |
74 | |
75 return 0 ; | |
76 } | |
77 | |
78 static int libdirac_decode_frame(AVCodecContext *avccontext, | |
79 void *data, int *data_size, | |
80 const uint8_t *buf, int buf_size) | |
81 { | |
82 | |
83 FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data; | |
84 AVPicture *picture = data; | |
85 AVPicture pic; | |
86 int pict_size; | |
87 unsigned char *buffer[3]; | |
88 | |
89 *data_size = 0; | |
90 | |
8422
e623323d409f
Fix incorrectly constructed Dirac parse units that caused A/V sync loss.
diego
parents:
7040
diff
changeset
|
91 if (buf_size>0) { |
6734 | 92 /* set data to decode into buffer */ |
93 dirac_buffer (p_dirac_params->p_decoder, buf, buf+buf_size); | |
8422
e623323d409f
Fix incorrectly constructed Dirac parse units that caused A/V sync loss.
diego
parents:
7040
diff
changeset
|
94 if ((buf[4] &0x08) == 0x08 && (buf[4] & 0x03)) |
e623323d409f
Fix incorrectly constructed Dirac parse units that caused A/V sync loss.
diego
parents:
7040
diff
changeset
|
95 avccontext->has_b_frames = 1; |
e623323d409f
Fix incorrectly constructed Dirac parse units that caused A/V sync loss.
diego
parents:
7040
diff
changeset
|
96 } |
6734 | 97 while (1) { |
98 /* parse data and process result */ | |
99 DecoderState state = dirac_parse (p_dirac_params->p_decoder); | |
100 switch (state) | |
101 { | |
102 case STATE_BUFFER: | |
103 return buf_size; | |
104 | |
105 case STATE_SEQUENCE: | |
106 { | |
107 /* tell FFmpeg about sequence details */ | |
108 dirac_sourceparams_t *src_params = | |
109 &p_dirac_params->p_decoder->src_params; | |
110 | |
111 if (avcodec_check_dimensions(avccontext, src_params->width, | |
112 src_params->height) < 0) { | |
113 av_log(avccontext, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n", | |
114 src_params->width, src_params->height); | |
115 avccontext->height = avccontext->width = 0; | |
116 return -1; | |
117 } | |
118 | |
119 avccontext->height = src_params->height; | |
120 avccontext->width = src_params->width; | |
121 | |
122 avccontext->pix_fmt = GetFfmpegChromaFormat(src_params->chroma); | |
123 if (avccontext->pix_fmt == PIX_FMT_NONE) { | |
124 av_log (avccontext, AV_LOG_ERROR, | |
125 "Dirac chroma format %d not supported currently\n", | |
126 src_params->chroma); | |
127 return -1; | |
128 } | |
129 | |
130 avccontext->time_base.den = src_params->frame_rate.numerator; | |
131 avccontext->time_base.num = src_params->frame_rate.denominator; | |
132 | |
133 /* calculate output dimensions */ | |
134 avpicture_fill(&pic, NULL, avccontext->pix_fmt, | |
135 avccontext->width, avccontext->height); | |
136 | |
137 pict_size = avpicture_get_size(avccontext->pix_fmt, | |
138 avccontext->width, | |
139 avccontext->height); | |
140 | |
141 /* allocate output buffer */ | |
142 if (p_dirac_params->p_out_frame_buf == NULL) | |
143 p_dirac_params->p_out_frame_buf = av_malloc (pict_size); | |
144 buffer[0] = p_dirac_params->p_out_frame_buf; | |
145 buffer[1] = p_dirac_params->p_out_frame_buf + | |
146 pic.linesize[0] * avccontext->height; | |
147 buffer[2] = buffer[1] + | |
148 pic.linesize[1] * src_params->chroma_height; | |
149 | |
150 /* tell Dirac about output destination */ | |
151 dirac_set_buf(p_dirac_params->p_decoder, buffer, NULL); | |
152 break; | |
153 } | |
154 case STATE_SEQUENCE_END: | |
155 break; | |
156 | |
157 case STATE_PICTURE_AVAIL: | |
158 /* fill picture with current buffer data from Dirac */ | |
159 avpicture_fill(picture, p_dirac_params->p_out_frame_buf, | |
160 avccontext->pix_fmt, | |
161 avccontext->width, avccontext->height); | |
162 *data_size = sizeof(AVPicture); | |
163 return buf_size; | |
164 | |
165 case STATE_INVALID: | |
166 return -1; | |
167 | |
168 default: | |
169 break; | |
170 } | |
171 } | |
172 | |
173 return buf_size; | |
174 } | |
175 | |
176 | |
177 static int libdirac_decode_close(AVCodecContext *avccontext) | |
178 { | |
179 FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data; | |
180 dirac_decoder_close (p_dirac_params->p_decoder); | |
181 | |
182 av_freep(&p_dirac_params->p_out_frame_buf); | |
183 | |
184 return 0 ; | |
185 } | |
186 | |
187 static void libdirac_flush (AVCodecContext *avccontext) | |
188 { | |
189 /* Got a seek request. We will need free memory held in the private | |
190 * context and free the current Dirac decoder handle and then open | |
191 * a new decoder handle. */ | |
192 libdirac_decode_close (avccontext); | |
193 libdirac_decode_init (avccontext); | |
194 return; | |
195 } | |
196 | |
197 | |
198 | |
199 AVCodec libdirac_decoder = { | |
200 "libdirac", | |
201 CODEC_TYPE_VIDEO, | |
202 CODEC_ID_DIRAC, | |
203 sizeof(FfmpegDiracDecoderParams), | |
204 libdirac_decode_init, | |
205 NULL, | |
206 libdirac_decode_close, | |
207 libdirac_decode_frame, | |
208 CODEC_CAP_DELAY, | |
6819
43bede126ef6
missing codec long names by Stefano Sabatini, stefano.sabatini-lala poste it
diego
parents:
6734
diff
changeset
|
209 .flush = libdirac_flush, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6819
diff
changeset
|
210 .long_name = NULL_IF_CONFIG_SMALL("libdirac Dirac 2.2"), |
6734 | 211 } ; |