8 FFMPEG::FFMPEG(Asset *asset) {
16 int FFMPEG::init(char *codec_string) {
19 avcodec_register_all();
21 CodecID id = codec_id(codec_string);
22 codec = avcodec_find_decoder(id);
24 printf("FFMPEG::init no decoder for '%s'", codec_string);
28 context = avcodec_alloc_context();
30 if (avcodec_open(context, codec)) {
31 printf("FFMPEG::init avcodec_open() failed\n");
34 picture = avcodec_alloc_frame();
41 avcodec_close(context);
47 CodecID FFMPEG::codec_id(char *codec_string) {
48 #define CODEC_IS(x) (! strncmp(codec_string, x, 4))
50 if (CODEC_IS(QUICKTIME_DV) ||
51 CODEC_IS(QUICKTIME_DVSD)) return CODEC_ID_DVVIDEO;
53 if (CODEC_IS(QUICKTIME_MP4V) ||
54 CODEC_IS(QUICKTIME_DIVX)) return CODEC_ID_MPEG4;
61 PixelFormat FFMPEG::color_model_to_pix_fmt(int color_model) {
65 return PIX_FMT_YUV422;
68 case BC_BGR8888: // NOTE: order flipped
69 return PIX_FMT_RGBA32;
73 return PIX_FMT_YUV420P;
75 return PIX_FMT_YUV422P;
77 return PIX_FMT_YUV444P;
79 return PIX_FMT_YUV411P;
81 return PIX_FMT_RGB565;
87 int FFMPEG::pix_fmt_to_color_model(PixelFormat pix_fmt) {
100 case PIX_FMT_YUV422P:
102 case PIX_FMT_YUV444P:
104 case PIX_FMT_YUV411P:
110 return BC_TRANSPARENCY;
113 int FFMPEG::init_picture_from_frame(AVPicture *picture, VFrame *frame) {
114 int cmodel = frame->get_color_model();
115 PixelFormat pix_fmt = color_model_to_pix_fmt(cmodel);
117 int size = avpicture_fill(picture, frame->get_data(), pix_fmt,
118 frame->get_w(), frame->get_h());
121 printf("FFMPEG::init_picture failed\n");
125 if (cmodel_is_planar(frame->get_color_model())) {
126 // override avpicture_fill() for planar types
127 picture->data[0] = frame->get_y();
128 picture->data[1] = frame->get_u();
129 picture->data[2] = frame->get_v();
136 int FFMPEG::convert_cmodel(VFrame *frame_in, VFrame *frame_out) {
138 PixelFormat pix_fmt_in =
139 color_model_to_pix_fmt(frame_in->get_color_model());
140 PixelFormat pix_fmt_out =
141 color_model_to_pix_fmt(frame_out->get_color_model());
143 // do conversion within libavcodec if possible
144 if (pix_fmt_in != PIX_FMT_NB && pix_fmt_out != PIX_FMT_NB) {
145 // set up a temporary pictures from frame_in and frame_out
146 AVPicture picture_in, picture_out;
147 init_picture_from_frame(&picture_in, frame_in);
148 init_picture_from_frame(&picture_out, frame_out);
150 int result = img_convert(&picture_out,
157 printf("FFMPEG::convert_cmodel img_convert() failed\n");
163 // failing the fast method, use the failsafe cmodel_transfer()
164 return convert_cmodel_transfer(frame_in, frame_out);
167 int FFMPEG::convert_cmodel_transfer(VFrame *frame_in, VFrame *frame_out) {
169 // WARNING: cmodel_transfer is said to be broken with BC_YUV411P
172 frame_out->get_rows(),
174 frame_in->get_rows(),
177 frame_out->get_y(), frame_out->get_u(), frame_out->get_v(),
179 frame_in->get_y(), frame_in->get_u(), frame_in->get_v(),
182 0, 0, frame_in->get_w(), frame_in->get_h(),
184 0, 0, frame_out->get_w(), frame_out->get_h(),
187 frame_in->get_color_model(), frame_out->get_color_model(),
192 // Rowspans (of luma for YUV)
193 frame_in->get_w(), frame_out->get_w()
201 int FFMPEG::convert_cmodel(AVPicture *picture_in, PixelFormat pix_fmt_in,
202 int width_in, int height_in, VFrame *frame_out) {
204 // set up a temporary picture_out from frame_out
205 AVPicture picture_out;
206 init_picture_from_frame(&picture_out, frame_out);
207 int cmodel_out = frame_out->get_color_model();
208 PixelFormat pix_fmt_out = color_model_to_pix_fmt(cmodel_out);
210 // do conversion within libavcodec if possible
211 if (pix_fmt_out != PIX_FMT_NB) {
212 int result = img_convert(&picture_out,
219 printf("FFMPEG::convert_cmodel img_convert() failed\n");
224 // make an intermediate temp frame only if necessary
225 int cmodel_in = pix_fmt_to_color_model(pix_fmt_in);
226 if (cmodel_in == BC_TRANSPARENCY) {
227 if (pix_fmt_in == PIX_FMT_RGBA32) {
228 // avoid infinite recursion if things are broken
229 printf("FFMPEG::convert_cmodel pix_fmt_in broken!\n");
233 // NOTE: choose RGBA8888 as a hopefully non-lossy colormodel
234 VFrame *temp_frame = new VFrame(0, width_in, height_in,
236 if (convert_cmodel(picture_in, pix_fmt_in,
237 width_in, height_in, temp_frame)) {
239 return 1; // recursed call will print error message
242 int result = convert_cmodel(temp_frame, frame_out);
248 // NOTE: no scaling possible in img_convert() so none possible here
249 if (frame_out->get_w() != width_in ||
250 frame_out->get_h() != height_in) {
251 printf("scaling from %sx%s to %sx%x not allowed\n",
253 frame_out->get_w(), frame_out->get_h());
258 // if we reach here we know that cmodel_transfer() will work
259 uint8_t *yuv_in[3] = {0,0,0};
260 uint8_t *row_pointers_in[height_in];
261 if (cmodel_is_planar(cmodel_in)) {
262 yuv_in[0] = picture_in->data[0];
263 yuv_in[1] = picture_in->data[1];
264 yuv_in[2] = picture_in->data[2];
267 // set row pointers for picture_in
268 uint8_t *data = picture_in->data[0];
270 cmodel_calculate_pixelsize(cmodel_in) * height_in;
271 for (int i = 0; i < height_in; i++) {
272 row_pointers_in[i] = data + i * bytes_per_line;
278 frame_out->get_rows(),
283 frame_out->get_y(), frame_out->get_u(), frame_out->get_v(),
285 yuv_in[0], yuv_in[1], yuv_in[2],
288 0, 0, width_in, height_in, // NOTE: dimensions are same
290 0, 0, width_in, height_in,
292 // Color model in, color model out
293 cmodel_in, cmodel_out,
298 // Rowspans in, out (of luma for YUV)
306 int FFMPEG::decode(uint8_t *data, long data_size, VFrame *frame_out) {
308 // NOTE: frame must already have data space allocated
311 int length = avcodec_decode_video(context,
318 printf("FFMPEG::decode error decoding frame\n");
323 // signal the caller there is no picture yet
324 return FFMPEG_LATENCY;
327 int result = convert_cmodel((AVPicture *)picture,