00001 #include "colormodels.h"
00002 #include "funcprotos.h"
00003 #include <pthread.h>
00004 #include "quicktime.h"
00005 #include "qtffmpeg.h"
00006 #include "qtprivate.h"
00007 #include <string.h>
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 int ffmpeg_initialized = 0;
00018 pthread_mutex_t ffmpeg_lock = PTHREAD_MUTEX_INITIALIZER;
00019
00020
00021
00022
00023
00024
00025 quicktime_ffmpeg_t* quicktime_new_ffmpeg(int cpus,
00026 int fields,
00027 int ffmpeg_id,
00028 int w,
00029 int h,
00030 quicktime_stsd_table_t *stsd_table)
00031 {
00032 quicktime_ffmpeg_t *ptr = calloc(1, sizeof(quicktime_ffmpeg_t));
00033 quicktime_esds_t *esds = &stsd_table->esds;
00034 quicktime_avcc_t *avcc = &stsd_table->avcc;
00035 int i;
00036
00037 ptr->fields = fields;
00038 ptr->width = w;
00039 ptr->height = h;
00040 ptr->ffmpeg_id = ffmpeg_id;
00041
00042 if(ffmpeg_id == CODEC_ID_SVQ1)
00043 {
00044 ptr->width_i = quicktime_quantize32(ptr->width);
00045 ptr->height_i = quicktime_quantize32(ptr->height);
00046 }
00047 else
00048 {
00049 ptr->width_i = quicktime_quantize16(ptr->width);
00050 ptr->height_i = quicktime_quantize16(ptr->height);
00051 }
00052
00053 pthread_mutex_lock(&ffmpeg_lock);
00054 if(!ffmpeg_initialized)
00055 {
00056 ffmpeg_initialized = 1;
00057 avcodec_init();
00058 avcodec_register_all();
00059 }
00060
00061 for(i = 0; i < fields; i++)
00062 {
00063 ptr->decoder[i] = avcodec_find_decoder(ptr->ffmpeg_id);
00064 if(!ptr->decoder[i])
00065 {
00066 printf("quicktime_new_ffmpeg: avcodec_find_decoder returned NULL.\n");
00067 quicktime_delete_ffmpeg(ptr);
00068 return 0;
00069 }
00070
00071 AVCodecContext *context = ptr->decoder_context[i] = avcodec_alloc_context();
00072 static char fake_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00073 context->width = ptr->width_i;
00074 context->height = ptr->height_i;
00075
00076
00077 context->extradata = fake_data;
00078 context->extradata_size = 0;
00079 if(esds->mpeg4_header && esds->mpeg4_header_size)
00080 {
00081 context->extradata = esds->mpeg4_header;
00082 context->extradata_size = esds->mpeg4_header_size;
00083 }
00084 if(avcc->data && avcc->data_size)
00085 {
00086 context->extradata = avcc->data;
00087 context->extradata_size = avcc->data_size;
00088 }
00089 if(cpus > 1 &&
00090 (ffmpeg_id == CODEC_ID_MPEG4 ||
00091 ffmpeg_id == CODEC_ID_MPEG1VIDEO ||
00092 ffmpeg_id == CODEC_ID_MPEG2VIDEO ||
00093 ffmpeg_id == CODEC_ID_H263P ||
00094 ffmpeg_id == CODEC_FLAG_H263P_SLICE_STRUCT))
00095 {
00096 avcodec_thread_init(context, cpus);
00097 context->thread_count = cpus;
00098 }
00099 if(avcodec_open(context,
00100 ptr->decoder[i]) < 0)
00101 {
00102 printf("quicktime_new_ffmpeg: avcodec_open failed.\n");
00103 quicktime_delete_ffmpeg(ptr);
00104 }
00105 ptr->last_frame[i] = -1;
00106 }
00107 pthread_mutex_unlock(&ffmpeg_lock);
00108
00109 return ptr;
00110 }
00111
00112
00113
00114 void quicktime_delete_ffmpeg(quicktime_ffmpeg_t *ptr)
00115 {
00116 int i;
00117 if(ptr)
00118 {
00119 pthread_mutex_lock(&ffmpeg_lock);
00120 for(i = 0; i < ptr->fields; i++)
00121 {
00122 if(ptr->decoder_context[i])
00123 {
00124 avcodec_close(ptr->decoder_context[i]);
00125 free(ptr->decoder_context[i]);
00126 }
00127 }
00128 pthread_mutex_unlock(&ffmpeg_lock);
00129
00130
00131
00132 if(ptr->temp_frame) free(ptr->temp_frame);
00133 if(ptr->work_buffer) free(ptr->work_buffer);
00134
00135
00136 free(ptr);
00137 }
00138 }
00139
00140
00141 static int decode_wrapper(quicktime_t *file,
00142 quicktime_video_map_t *vtrack,
00143 quicktime_ffmpeg_t *ffmpeg,
00144 int frame_number,
00145 int current_field,
00146 int track,
00147 int drop_it)
00148 {
00149 int got_picture = 0;
00150 int result = 0;
00151 int bytes = 0;
00152 int header_bytes = 0;
00153 char *compressor = vtrack->track->mdia.minf.stbl.stsd.table[0].format;
00154 quicktime_trak_t *trak = vtrack->track;
00155 quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
00156
00157
00158 quicktime_set_video_position(file, frame_number, track);
00159
00160 bytes = quicktime_frame_size(file, frame_number, track);
00161 if(frame_number == 0)
00162 {
00163 header_bytes = stsd_table->esds.mpeg4_header_size;
00164 }
00165
00166 if(!ffmpeg->work_buffer || ffmpeg->buffer_size < bytes + header_bytes)
00167 {
00168 if(ffmpeg->work_buffer) free(ffmpeg->work_buffer);
00169 ffmpeg->buffer_size = bytes + header_bytes;
00170 ffmpeg->work_buffer = calloc(1, ffmpeg->buffer_size + 100);
00171 }
00172
00173 if(header_bytes)
00174 memcpy(ffmpeg->work_buffer, stsd_table->esds.mpeg4_header, header_bytes);
00175
00176 if(!quicktime_read_data(file,
00177 ffmpeg->work_buffer + header_bytes,
00178 bytes))
00179 result = -1;
00180
00181
00182 if(!result)
00183 {
00184
00185
00186
00187
00188 if(drop_it)
00189 ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_NONREF ;
00190 else
00191 ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_DEFAULT;
00192 result = avcodec_decode_video(ffmpeg->decoder_context[current_field],
00193 &ffmpeg->picture[current_field],
00194 &got_picture,
00195 ffmpeg->work_buffer,
00196 bytes + header_bytes);
00197
00198
00199
00200 if(ffmpeg->picture[current_field].data[0])
00201 {
00202 result = 0;
00203 }
00204 else
00205 {
00206
00207
00208 result = 1;
00209 }
00210
00211 #ifdef ARCH_X86
00212 asm("emms");
00213 #endif
00214 }
00215
00216 return result;
00217 }
00218
00219
00220
00221 static int get_chroma_factor(quicktime_ffmpeg_t *ffmpeg, int current_field)
00222 {
00223 switch(ffmpeg->decoder_context[current_field]->pix_fmt)
00224 {
00225 case PIX_FMT_YUV420P:
00226 return 4;
00227 break;
00228 case PIX_FMT_YUV422:
00229 return 2;
00230 break;
00231 case PIX_FMT_YUV422P:
00232 return 2;
00233 break;
00234 case PIX_FMT_YUV410P:
00235 return 9;
00236 break;
00237 default:
00238 fprintf(stderr,
00239 "get_chroma_factor: unrecognized color model %d\n",
00240 ffmpeg->decoder_context[current_field]->pix_fmt);
00241 return 9;
00242 break;
00243 }
00244 }
00245
00246 int quicktime_ffmpeg_decode(quicktime_ffmpeg_t *ffmpeg,
00247 quicktime_t *file,
00248 unsigned char **row_pointers,
00249 int track)
00250 {
00251 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
00252 quicktime_trak_t *trak = vtrack->track;
00253 int current_field = vtrack->current_position % ffmpeg->fields;
00254 int input_cmodel;
00255 int result = 0;
00256 int seeking_done = 0;
00257 int i;
00258
00259
00260 result = quicktime_get_frame(vtrack->frame_cache,
00261 vtrack->current_position,
00262 &ffmpeg->picture[current_field].data[0],
00263 &ffmpeg->picture[current_field].data[1],
00264 &ffmpeg->picture[current_field].data[2]);
00265
00266
00267
00268 if(!result)
00269 {
00270
00271
00272
00273
00274
00275
00276
00277 if(ffmpeg->last_frame[current_field] == -1 &&
00278 ffmpeg->ffmpeg_id != CODEC_ID_H264)
00279 {
00280 int current_frame = vtrack->current_position;
00281
00282
00283
00284 result = decode_wrapper(file,
00285 vtrack,
00286 ffmpeg,
00287 current_field,
00288 current_field,
00289 track,
00290 0);
00291
00292 quicktime_set_video_position(file, current_frame, track);
00293 ffmpeg->last_frame[current_field] = current_field;
00294 }
00295
00296
00297
00298
00299 if(quicktime_has_keyframes(file, track) &&
00300
00301 vtrack->current_position != ffmpeg->last_frame[current_field] + ffmpeg->fields &&
00302
00303 vtrack->current_position != ffmpeg->last_frame[current_field])
00304 {
00305 int frame1;
00306 int first_frame;
00307 int frame2 = vtrack->current_position;
00308 int current_frame = frame2;
00309 int do_i_frame = 1;
00310
00311
00312
00313 if(!quicktime_has_frame(vtrack->frame_cache, vtrack->current_position + 1))
00314 quicktime_reset_cache(vtrack->frame_cache);
00315
00316
00317 frame1 = current_frame;
00318 do
00319 {
00320 frame1 = quicktime_get_keyframe_before(file,
00321 frame1 - 1,
00322 track);
00323 }while(frame1 > 0 && (frame1 % ffmpeg->fields) != current_field);
00324
00325
00326
00327
00328
00329 if( 0 )
00330 {
00331 do
00332 {
00333 frame1 = quicktime_get_keyframe_before(file,
00334 frame1 - 1,
00335 track);
00336 }while(frame1 > 0 && (frame1 & ffmpeg->fields) != current_field);
00337
00338 }
00339
00340
00341
00342
00343 if(frame1 < ffmpeg->last_frame[current_field] &&
00344 frame2 > ffmpeg->last_frame[current_field])
00345 {
00346 frame1 = ffmpeg->last_frame[current_field] + ffmpeg->fields;
00347 do_i_frame = 0;
00348 }
00349
00350 first_frame = frame1;
00351
00352
00353 while(frame1 <= frame2)
00354 {
00355 result = decode_wrapper(file,
00356 vtrack,
00357 ffmpeg,
00358 frame1,
00359 current_field,
00360 track,
00361
00362 0 );
00363
00364 if(ffmpeg->picture[current_field].data[0] &&
00365
00366 frame1 > first_frame)
00367 {
00368 int y_size = ffmpeg->picture[current_field].linesize[0] * ffmpeg->height_i;
00369 int u_size = y_size / get_chroma_factor(ffmpeg, current_field);
00370 int v_size = y_size / get_chroma_factor(ffmpeg, current_field);
00371 quicktime_put_frame(vtrack->frame_cache,
00372 frame1,
00373 ffmpeg->picture[current_field].data[0],
00374 ffmpeg->picture[current_field].data[1],
00375 ffmpeg->picture[current_field].data[2],
00376 y_size,
00377 u_size,
00378 v_size);
00379 }
00380
00381
00382
00383 if(do_i_frame)
00384 {
00385 result = decode_wrapper(file,
00386 vtrack,
00387 ffmpeg,
00388 frame1,
00389 current_field,
00390 track,
00391 0);
00392 do_i_frame = 0;
00393 }
00394 frame1 += ffmpeg->fields;
00395 }
00396
00397 vtrack->current_position = frame2;
00398 seeking_done = 1;
00399 }
00400
00401
00402 if(!seeking_done &&
00403
00404 vtrack->current_position != ffmpeg->last_frame[current_field])
00405 {
00406 result = decode_wrapper(file,
00407 vtrack,
00408 ffmpeg,
00409 vtrack->current_position,
00410 current_field,
00411 track,
00412 0);
00413 }
00414
00415
00416
00417
00418 ffmpeg->last_frame[current_field] = vtrack->current_position;
00419 }
00420
00421
00422 switch(ffmpeg->decoder_context[current_field]->pix_fmt)
00423 {
00424 case PIX_FMT_YUV420P:
00425 input_cmodel = BC_YUV420P;
00426 break;
00427 case PIX_FMT_YUV422:
00428 input_cmodel = BC_YUV422;
00429 break;
00430 case PIX_FMT_YUV422P:
00431 input_cmodel = BC_YUV422P;
00432 break;
00433 case PIX_FMT_YUV410P:
00434 input_cmodel = BC_YUV9P;
00435 break;
00436 default:
00437 fprintf(stderr,
00438 "quicktime_ffmpeg_decode: unrecognized color model %d\n",
00439 ffmpeg->decoder_context[current_field]->pix_fmt);
00440 input_cmodel = BC_YUV420P;
00441 break;
00442 }
00443
00444 if(ffmpeg->picture[current_field].data[0])
00445 {
00446 unsigned char **input_rows;
00447
00448 input_rows =
00449 malloc(sizeof(unsigned char*) *
00450 ffmpeg->decoder_context[current_field]->height);
00451
00452
00453 for(i = 0; i < ffmpeg->decoder_context[current_field]->height; i++)
00454 input_rows[i] = ffmpeg->picture[current_field].data[0] +
00455 i *
00456 ffmpeg->decoder_context[current_field]->width *
00457 cmodel_calculate_pixelsize(input_cmodel);
00458
00459
00460 cmodel_transfer(row_pointers,
00461 input_rows,
00462 row_pointers[0],
00463 row_pointers[1],
00464 row_pointers[2],
00465 ffmpeg->picture[current_field].data[0],
00466 ffmpeg->picture[current_field].data[1],
00467 ffmpeg->picture[current_field].data[2],
00468 file->in_x,
00469 file->in_y,
00470 file->in_w,
00471 file->in_h,
00472 0,
00473 0,
00474 file->out_w,
00475 file->out_h,
00476 input_cmodel,
00477 file->color_model,
00478 0,
00479 ffmpeg->picture[current_field].linesize[0],
00480 ffmpeg->width);
00481 free(input_rows);
00482 }
00483
00484
00485 return result;
00486 }
00487
00488
00489
00490
00491
00492