"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/div3.c" (9 Jan 2007, 15230 Bytes) of package /linux/privat/old/quicktime4linux-2.3-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "avcodec.h"
    2 #include "colormodels.h"
    3 #include "funcprotos.h"
    4 #include "quicktime.h"
    5 
    6 
    7 #include <pthread.h>
    8 
    9 
   10 
   11 typedef struct
   12 {
   13     int decode_initialized;
   14     int encode_initialized;
   15     AVCodec *decoder;
   16     AVCodecContext *decoder_context;
   17     AVCodecContext *encoder_context;
   18     AVFrame picture;
   19     char *temp_frame;
   20     char *work_buffer;
   21     int buffer_size;
   22     int last_frame;
   23     int got_key;
   24 // ID out of avcodec.h for the codec used
   25     int derivative;
   26 
   27 
   28     int bitrate;
   29     int bitrate_tolerance;
   30     int interlaced;
   31     int gop_size;
   32     int quantizer;
   33     int fix_bitrate;
   34 
   35 
   36     AVCodec *encoder;
   37 } quicktime_div3_codec_t;
   38 
   39 static pthread_mutex_t encode_mutex;
   40 static pthread_mutex_t decode_mutex;
   41 static int mutex_initialized = 0;
   42 static int global_initialized = 0;
   43 
   44 
   45 static int reads_colormodel(quicktime_t *file, 
   46         int colormodel, 
   47         int track)
   48 {
   49     return (colormodel == BC_YUV420P);
   50 }
   51 
   52 static int writes_colormodel(quicktime_t *file, 
   53         int colormodel, 
   54         int track)
   55 {
   56     return (colormodel == BC_RGB888 ||
   57         colormodel == BC_RGBA8888 ||
   58         colormodel == BC_RGB161616 ||
   59         colormodel == BC_RGBA16161616 ||
   60         colormodel == BC_YUV888 ||
   61         colormodel == BC_YUVA8888 ||
   62         colormodel == BC_YUV161616 ||
   63         colormodel == BC_YUVA16161616 ||
   64         colormodel == BC_YUV420P ||
   65         colormodel == BC_YUV422 ||
   66         colormodel == BC_COMPRESSED);
   67 }
   68 
   69 
   70 
   71 static void init_mutex()
   72 {
   73     if(!mutex_initialized)
   74     {
   75         pthread_mutexattr_t attr;
   76         mutex_initialized = 1;
   77         pthread_mutexattr_init(&attr);
   78         pthread_mutex_init(&decode_mutex, &attr);
   79         pthread_mutex_init(&encode_mutex, &attr);
   80     }
   81 }
   82 
   83 static int delete_codec(quicktime_video_map_t *vtrack)
   84 {
   85     quicktime_div3_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
   86     if(codec->decode_initialized)
   87     {
   88         pthread_mutex_lock(&decode_mutex);
   89         avcodec_close(codec->decoder_context);
   90         free(codec->decoder_context);
   91         pthread_mutex_unlock(&decode_mutex);
   92     }
   93     if(codec->encode_initialized)
   94     {
   95         pthread_mutex_lock(&encode_mutex);
   96         avcodec_close(codec->encoder_context);
   97         free(codec->encoder_context);
   98         pthread_mutex_unlock(&encode_mutex);
   99     }
  100     if(codec->temp_frame) free(codec->temp_frame);
  101     if(codec->work_buffer) free(codec->work_buffer);
  102     free(codec);
  103 }
  104 
  105 static int init_codec(quicktime_div3_codec_t *codec, int width_i, int height_i)
  106 {
  107     if(!global_initialized)
  108     {
  109         global_initialized = 1;
  110         avcodec_init();
  111         avcodec_register_all();
  112     }
  113 
  114 
  115     codec->decoder = avcodec_find_decoder(codec->derivative);
  116     if(!codec->decoder)
  117     {
  118         printf("init_codec: avcodec_find_decoder returned NULL.\n");
  119         return 1;
  120     }
  121 
  122     codec->decoder_context = avcodec_alloc_context();
  123     codec->decoder_context->width = width_i;
  124     codec->decoder_context->height = height_i;
  125     if(avcodec_open(codec->decoder_context, codec->decoder) < 0)
  126     {
  127         printf("init_codec: avcodec_open failed.\n");
  128     }
  129     return 0;
  130 }
  131 
  132 
  133 
  134 
  135 
  136 int quicktime_div3_is_key(unsigned char *data, long size)
  137 {
  138     int result = 0;
  139 
  140 // First 2 bits are pict type.
  141     result = (data[0] & 0xc0) == 0;
  142 
  143 
  144     return result;
  145 }
  146 
  147 
  148 static int decode_wrapper(quicktime_div3_codec_t *codec,
  149     unsigned char *data, 
  150     long size)
  151 {
  152     int got_picture = 0;
  153     int result;
  154 
  155     if(!codec->got_key && !quicktime_div3_is_key(data, size)) return 0;
  156 
  157     if(quicktime_div3_is_key(data, size)) codec->got_key = 1;
  158 
  159     result = avcodec_decode_video(codec->decoder_context, 
  160         &codec->picture,
  161         &got_picture,
  162         codec->work_buffer,
  163         size);
  164 #ifdef ARCH_X86
  165     asm("emms");
  166 #endif
  167     return result;
  168 }
  169 
  170 
  171 
  172 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
  173 {
  174 //printf(__FUNCTION__ " div3 1\n");
  175     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  176     quicktime_div3_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  177     quicktime_trak_t *trak = vtrack->track;
  178     int result = 0;
  179     int width = trak->tkhd.track_width;
  180     int height = trak->tkhd.track_height;
  181     int width_i = (int)((float)width / 16 + 0.5) * 16;
  182     int height_i = (int)((float)height / 16 + 0.5) * 16;
  183     int input_cmodel;
  184     int bytes;
  185     int i;
  186     unsigned char **input_rows;
  187 
  188     init_mutex();
  189     pthread_mutex_lock(&decode_mutex);
  190 
  191 
  192     if(!codec->decode_initialized)
  193     {
  194         init_codec(codec, width_i, height_i);
  195 
  196         codec->decode_initialized = 1;
  197     }
  198 
  199 // Handle seeking
  200     if(quicktime_has_keyframes(file, track) && 
  201         vtrack->current_position != codec->last_frame + 1)
  202     {
  203         int frame1, frame2 = vtrack->current_position;
  204 
  205         frame1 = quicktime_get_keyframe_before(file,
  206             vtrack->current_position, 
  207             track);
  208 
  209         if(frame1 < codec->last_frame &&
  210             frame2 > codec->last_frame) frame1 = codec->last_frame + 1;
  211 
  212         while(frame1 < frame2)
  213         {
  214 
  215             quicktime_set_video_position(file, frame1, track);
  216 
  217             bytes = quicktime_frame_size(file, frame1, track);
  218 
  219             if(!codec->work_buffer || codec->buffer_size < bytes)
  220             {
  221                 if(codec->work_buffer) free(codec->work_buffer);
  222                 codec->buffer_size = bytes;
  223                 codec->work_buffer = calloc(1, codec->buffer_size + 100);
  224             }
  225 
  226 
  227             result = !quicktime_read_data(file, 
  228                 codec->work_buffer, 
  229                 bytes);
  230 
  231 
  232             if(!result)
  233                 result = decode_wrapper(codec,
  234                     codec->work_buffer, 
  235                     bytes);
  236 
  237             frame1++;
  238         }
  239 
  240         vtrack->current_position = frame2;
  241     }
  242 
  243     codec->last_frame = vtrack->current_position;
  244     bytes = quicktime_frame_size(file, vtrack->current_position, track);
  245     quicktime_set_video_position(file, vtrack->current_position, track);
  246 
  247     if(!codec->work_buffer || codec->buffer_size < bytes)
  248     {
  249         if(codec->work_buffer) free(codec->work_buffer);
  250         codec->buffer_size = bytes;
  251         codec->work_buffer = calloc(1, codec->buffer_size + 100);
  252     }
  253     result = !quicktime_read_data(file, codec->work_buffer, bytes);
  254     
  255     if(!result)
  256         result = decode_wrapper(codec,
  257             codec->work_buffer, 
  258             bytes);
  259 
  260     pthread_mutex_unlock(&decode_mutex);
  261 
  262 
  263 
  264 
  265 
  266 
  267 
  268 
  269 
  270 
  271 
  272     result = (result <= 0);
  273     switch(codec->decoder_context->pix_fmt)
  274     {
  275         case PIX_FMT_YUV420P:
  276             input_cmodel = BC_YUV420P;
  277             break;
  278         case PIX_FMT_YUV422:
  279             input_cmodel = BC_YUV422;
  280             break;
  281         case PIX_FMT_YUV422P:
  282             input_cmodel = BC_YUV422P;
  283             break;
  284     }
  285 
  286 
  287     if(!result)
  288     {
  289         int y_out_size = codec->decoder_context->width * 
  290             codec->decoder_context->height;
  291         int u_out_size = codec->decoder_context->width * 
  292             codec->decoder_context->height / 
  293             4;
  294         int v_out_size = codec->decoder_context->width * 
  295             codec->decoder_context->height / 
  296             4;
  297         int y_in_size = codec->picture.linesize[0] * 
  298             codec->decoder_context->height;
  299         int u_in_size = codec->picture.linesize[1] * 
  300             codec->decoder_context->height / 
  301             4;
  302         int v_in_size = codec->picture.linesize[2] * 
  303             codec->decoder_context->height / 
  304             4;
  305         input_rows = 
  306             malloc(sizeof(unsigned char*) * 
  307             codec->decoder_context->height);
  308 
  309         for(i = 0; i < codec->decoder_context->height; i++)
  310             input_rows[i] = codec->picture.data[0] + 
  311                 i * 
  312                 codec->decoder_context->width * 
  313                 cmodel_calculate_pixelsize(input_cmodel);
  314 
  315         if(!codec->temp_frame)
  316         {
  317             codec->temp_frame = malloc(y_out_size +
  318                 u_out_size +
  319                 v_out_size);
  320         }
  321 
  322         if(codec->picture.data[0])
  323         {
  324             for(i = 0; i < codec->decoder_context->height; i++)
  325             {
  326                 memcpy(codec->temp_frame + i * codec->decoder_context->width,
  327                     codec->picture.data[0] + i * codec->picture.linesize[0],
  328                     codec->decoder_context->width);
  329             }
  330 
  331             for(i = 0; i < codec->decoder_context->height; i += 2)
  332             {
  333                 memcpy(codec->temp_frame + 
  334                         y_out_size + 
  335                         i / 2 * 
  336                         codec->decoder_context->width / 2,
  337                     codec->picture.data[1] + 
  338                         i / 2 * 
  339                         codec->picture.linesize[1],
  340                     codec->decoder_context->width / 2);
  341 
  342                 memcpy(codec->temp_frame + 
  343                         y_out_size + 
  344                         u_out_size + 
  345                         i / 2 * 
  346                         codec->decoder_context->width / 2,
  347                     codec->picture.data[2] + 
  348                         i / 2 * 
  349                         codec->picture.linesize[2],
  350                     codec->decoder_context->width / 2);
  351             }
  352         }
  353 
  354         cmodel_transfer(row_pointers, /* Leave NULL if non existent */
  355             input_rows,
  356             row_pointers[0], /* Leave NULL if non existent */
  357             row_pointers[1],
  358             row_pointers[2],
  359             codec->temp_frame, /* Leave NULL if non existent */
  360             codec->temp_frame + y_out_size,
  361             codec->temp_frame + y_out_size + u_out_size,
  362             file->in_x,        /* Dimensions to capture from input frame */
  363             file->in_y, 
  364             file->in_w, 
  365             file->in_h,
  366             0,       /* Dimensions to project on output frame */
  367             0, 
  368             file->out_w, 
  369             file->out_h,
  370             input_cmodel, 
  371             file->color_model,
  372             0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
  373             codec->decoder_context->width,       /* For planar use the luma rowspan */
  374             width);
  375 
  376         free(input_rows);
  377     }
  378 
  379 
  380     return result;
  381 }
  382 
  383 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
  384 {
  385 //printf(__FUNCTION__ " 1\n");
  386     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  387     quicktime_div3_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  388     quicktime_trak_t *trak = vtrack->track;
  389     int width = trak->tkhd.track_width;
  390     int height = trak->tkhd.track_height;
  391     int result = 0;
  392     int width_i = (int)((float)width / 16 + 0.5) * 16;
  393     int height_i = (int)((float)height / 16 + 0.5) * 16;
  394     AVFrame pict_tmp;
  395     int bytes;
  396     quicktime_atom_t chunk_atom;
  397 //printf(__FUNCTION__ " 1\n");
  398 
  399     init_mutex();
  400 //printf(__FUNCTION__ " 1\n");
  401 
  402     pthread_mutex_lock(&encode_mutex);
  403     if(!codec->encode_initialized)
  404     {
  405         static char *video_rc_eq="tex^qComp";
  406         codec->encode_initialized = 1;
  407         if(!global_initialized)
  408         {
  409             global_initialized = 1;
  410             avcodec_init();
  411             avcodec_register_all();
  412         }
  413 
  414         codec->encoder = avcodec_find_encoder(codec->derivative);
  415         if(!codec->encoder)
  416         {
  417             printf("encode: avcodec_find_encoder returned NULL.\n");
  418             pthread_mutex_unlock(&encode_mutex);
  419             return 1;
  420         }
  421 
  422         codec->encoder_context = avcodec_alloc_context();
  423         codec->encoder_context->frame_rate = FRAME_RATE_BASE *
  424             quicktime_frame_rate(file, track);
  425         codec->encoder_context->width = width_i;
  426         codec->encoder_context->height = height_i;
  427         codec->encoder_context->gop_size = codec->gop_size;
  428         codec->encoder_context->pix_fmt = PIX_FMT_YUV420P;
  429         codec->encoder_context->bit_rate = codec->bitrate;
  430         codec->encoder_context->bit_rate_tolerance = codec->bitrate_tolerance;
  431         codec->encoder_context->rc_eq = video_rc_eq;
  432         codec->encoder_context->qmin = 2;
  433         codec->encoder_context->qmax = 31;
  434         codec->encoder_context->max_qdiff = 3;
  435         codec->encoder_context->qblur = 0.5;
  436         codec->encoder_context->qcompress = 0.5;
  437         codec->encoder_context->me_method = ME_FULL;
  438 
  439         if(!codec->fix_bitrate)
  440         {
  441             codec->encoder_context->flags |= CODEC_FLAG_QSCALE;
  442         }
  443 
  444         if(codec->interlaced)
  445         {
  446             codec->encoder_context->flags |= CODEC_FLAG_INTERLACED_DCT;
  447         }
  448 
  449 
  450         avcodec_open(codec->encoder_context, codec->encoder);
  451 
  452         codec->work_buffer = calloc(1, width_i * height_i * 3);
  453         codec->buffer_size = width_i * height_i * 3;
  454     }
  455 //printf(__FUNCTION__ " 1\n");
  456 
  457 
  458 
  459     if(width_i == width && 
  460         height_i == height && 
  461         file->color_model == BC_YUV420P)
  462     {
  463         pict_tmp.data[0] = row_pointers[0];
  464         pict_tmp.data[1] = row_pointers[1];
  465         pict_tmp.data[2] = row_pointers[2];
  466         pict_tmp.linesize[0] = width_i;
  467         pict_tmp.linesize[1] = width_i / 2;
  468         pict_tmp.linesize[2] = width_i / 2;
  469     }
  470     else
  471     {
  472 //printf(__FUNCTION__ " 1\n");
  473         if(!codec->temp_frame)
  474         {
  475             codec->temp_frame = malloc(width_i * height_i * 3 / 2);
  476         }
  477 //printf(__FUNCTION__ " 1\n");
  478 
  479         cmodel_transfer(0, /* Leave NULL if non existent */
  480             row_pointers,
  481             codec->temp_frame, /* Leave NULL if non existent */
  482             codec->temp_frame + width_i * height_i,
  483             codec->temp_frame + width_i * height_i + width_i * height_i / 4,
  484             row_pointers[0], /* Leave NULL if non existent */
  485             row_pointers[1],
  486             row_pointers[2],
  487             0,        /* Dimensions to capture from input frame */
  488             0, 
  489             width, 
  490             height,
  491             0,       /* Dimensions to project on output frame */
  492             0, 
  493             width, 
  494             height,
  495             file->color_model, 
  496             BC_YUV420P,
  497             0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
  498             width,       /* For planar use the luma rowspan */
  499             width_i);
  500 //printf(__FUNCTION__ " 1\n");
  501 
  502         pict_tmp.data[0] = codec->temp_frame;
  503         pict_tmp.data[1] = codec->temp_frame + width_i * height_i;
  504         pict_tmp.data[2] = codec->temp_frame + width_i * height_i + width_i * height_i / 4;
  505         pict_tmp.linesize[0] = width_i;
  506         pict_tmp.linesize[1] = width_i / 2;
  507         pict_tmp.linesize[2] = width_i / 2;
  508     }
  509 
  510 
  511 //printf("encode 1\n");
  512     if(codec->quantizer >= 0)
  513         pict_tmp.quality = codec->quantizer;
  514     bytes = avcodec_encode_video(codec->encoder_context, 
  515         codec->work_buffer, 
  516         codec->buffer_size, 
  517         &pict_tmp);
  518     pthread_mutex_unlock(&encode_mutex);
  519 //printf("encode 100\n");
  520 
  521     quicktime_write_chunk_header(file, trak, &chunk_atom);
  522 //printf(__FUNCTION__ " 1\n");
  523     result = !quicktime_write_data(file, 
  524         codec->work_buffer, 
  525         bytes);
  526 //printf(__FUNCTION__ " 1\n");
  527 
  528     quicktime_write_chunk_footer(file, 
  529                     trak,
  530                     vtrack->current_chunk,
  531                     &chunk_atom, 
  532                     1);
  533 //printf(__FUNCTION__ " 1\n");
  534     if(pict_tmp.key_frame)
  535         quicktime_insert_keyframe(file, 
  536             vtrack->current_position, 
  537             track);
  538     vtrack->current_chunk++;
  539 
  540 //printf(__FUNCTION__ " 100\n");
  541 
  542 
  543 
  544 
  545     return result;
  546 }
  547 
  548 
  549 
  550 static int set_parameter(quicktime_t *file,
  551     int track,
  552     char *key,
  553     void *value)
  554 {
  555     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  556     quicktime_div3_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  557     if(!strcasecmp(key, "div3_bitrate"))
  558         codec->bitrate = *(int*)value;
  559     else
  560     if(!strcasecmp(key, "div3_bitrate_tolerance"))
  561         codec->bitrate_tolerance = *(int*)value;
  562     else
  563     if(!strcasecmp(key, "div3_interlaced"))
  564         codec->quantizer = *(int*)value;
  565     else
  566     if(!strcasecmp(key, "div3_gop_size"))
  567         codec->gop_size = *(int*)value;
  568     else
  569     if(!strcasecmp(key, "div3_quantizer"))
  570         codec->quantizer = *(int*)value;
  571     else
  572     if(!strcasecmp(key, "div3_fix_bitrate"))
  573         codec->fix_bitrate = *(int*)value;
  574 
  575     return 0;
  576 }
  577 
  578 
  579 void quicktime_init_codec_div3(quicktime_video_map_t *vtrack)
  580 {
  581     quicktime_div3_codec_t *codec;
  582     ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_div3_codec_t));
  583     ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = delete_codec;
  584     ((quicktime_codec_t*)vtrack->codec)->decode_video = decode;
  585     ((quicktime_codec_t*)vtrack->codec)->encode_video = encode;
  586     ((quicktime_codec_t*)vtrack->codec)->reads_colormodel = reads_colormodel;
  587     ((quicktime_codec_t*)vtrack->codec)->writes_colormodel = writes_colormodel;
  588     ((quicktime_codec_t*)vtrack->codec)->set_parameter = set_parameter;
  589 
  590     codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  591     codec->derivative = CODEC_ID_MSMPEG4V3;
  592 //  codec->derivative = CODEC_ID_MPEG4;
  593     codec->quantizer = -1;
  594 }
  595 
  596 
  597 
  598 
  599 
  600 
  601 void quicktime_init_codec_div4(quicktime_video_map_t *vtrack)
  602 {
  603     quicktime_div3_codec_t *codec;
  604     ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_div3_codec_t));
  605     ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = delete_codec;
  606     ((quicktime_codec_t*)vtrack->codec)->decode_video = decode;
  607     ((quicktime_codec_t*)vtrack->codec)->encode_video = encode;
  608     ((quicktime_codec_t*)vtrack->codec)->reads_colormodel = reads_colormodel;
  609     ((quicktime_codec_t*)vtrack->codec)->writes_colormodel = writes_colormodel;
  610     ((quicktime_codec_t*)vtrack->codec)->set_parameter = set_parameter;
  611 
  612     codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  613     codec->derivative = CODEC_ID_MPEG4;
  614     codec->quantizer = -1;
  615 }
  616 
  617 
  618 
  619