"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/qth264.c" (10 Aug 2008, 12800 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 <pthread.h>
    5 #include "qtffmpeg.h"
    6 #include "quicktime.h"
    7 #include <string.h>
    8 #include "workarounds.h"
    9 #include "x264.h"
   10 
   11 // This generates our own header using fixed parameters
   12 //#define MANUAL_HEADER
   13 
   14 // For the working version
   15 #define GOOD_VERSION
   16 
   17 typedef struct
   18 {
   19 // Encoder side
   20     x264_t *encoder[FIELDS];
   21     x264_picture_t *pic[FIELDS];
   22     x264_param_t param;
   23 
   24     int encode_initialized[FIELDS];
   25 
   26 // Temporary storage for color conversions
   27     char *temp_frame;
   28 // Storage of compressed data
   29     unsigned char *work_buffer;
   30 // Amount of data in work_buffer
   31     int buffer_size;
   32     int total_fields;
   33 // Set by flush to get the header
   34     int header_only;
   35 
   36 // Decoder side
   37     quicktime_ffmpeg_t *decoder;
   38 
   39 } quicktime_h264_codec_t;
   40 
   41 static pthread_mutex_t h264_lock = PTHREAD_MUTEX_INITIALIZER;
   42 
   43 
   44 
   45 
   46 
   47 
   48 
   49 
   50 
   51 
   52 
   53 
   54 // Direct copy routines
   55 int quicktime_h264_is_key(unsigned char *data, long size, char *codec_id)
   56 {
   57     
   58 }
   59 
   60 
   61 
   62 
   63 static int delete_codec(quicktime_video_map_t *vtrack)
   64 {
   65     quicktime_h264_codec_t *codec;
   66     int i;
   67 
   68 
   69     codec = ((quicktime_codec_t*)vtrack->codec)->priv;
   70     for(i = 0; i < codec->total_fields; i++)
   71     {
   72         if(codec->encode_initialized[i])
   73         {
   74             pthread_mutex_lock(&h264_lock);
   75 
   76 
   77             if(codec->pic[i])
   78             {
   79                 x264_picture_clean(codec->pic[i]);
   80                 free(codec->pic[i]);
   81             }
   82 
   83             if(codec->encoder[i])
   84             {
   85                 x264_encoder_close(codec->encoder[i]);
   86             }
   87 
   88             pthread_mutex_unlock(&h264_lock);
   89         }
   90     }
   91 
   92     
   93 
   94     if(codec->temp_frame) free(codec->temp_frame);
   95     if(codec->work_buffer) free(codec->work_buffer);
   96     if(codec->decoder) quicktime_delete_ffmpeg(codec->decoder);
   97 
   98 
   99     free(codec);
  100     return 0;
  101 }
  102 
  103 
  104 
  105 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
  106 {
  107     int64_t offset = quicktime_position(file);
  108     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  109     quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  110     quicktime_trak_t *trak = vtrack->track;
  111     int width = quicktime_video_width(file, track);
  112     int height = quicktime_video_height(file, track);
  113     int w_16 = quicktime_quantize16(width);
  114     int h_16 = quicktime_quantize16(height);
  115     int i;
  116     int result = 0;
  117     int bytes = 0;
  118     int is_keyframe = 0;
  119     int current_field = vtrack->current_position % codec->total_fields;
  120     quicktime_atom_t chunk_atom;
  121     unsigned char header[1024];
  122     int header_size = 0;
  123     int got_pps = 0;
  124     int got_sps = 0;
  125     quicktime_avcc_t *avcc = &trak->mdia.minf.stbl.stsd.table[0].avcc;
  126 
  127 
  128 
  129 
  130 
  131 
  132     pthread_mutex_lock(&h264_lock);
  133 
  134     if(!codec->encode_initialized[current_field])
  135     {
  136         codec->encode_initialized[current_field] = 1;
  137         codec->param.i_width = w_16;
  138         codec->param.i_height = h_16;
  139         codec->param.i_fps_num = quicktime_frame_rate_n(file, track);
  140         codec->param.i_fps_den = quicktime_frame_rate_d(file, track);
  141 
  142 #ifndef GOOD_VERSION
  143         codec->param.rc.i_rc_method = X264_RC_CQP;
  144 #endif
  145 
  146 // Reset quantizer if fixed bitrate
  147         x264_param_t default_params;
  148         x264_param_default(&default_params);
  149 #ifdef GOOD_VERSION
  150         if(codec->param.rc.b_cbr)
  151 #else
  152         if(codec->param.rc.i_qp_constant)
  153 #endif
  154         {
  155             codec->param.rc.i_qp_constant = default_params.rc.i_qp_constant;
  156             codec->param.rc.i_qp_min = default_params.rc.i_qp_min;
  157             codec->param.rc.i_qp_max = default_params.rc.i_qp_max;
  158         }
  159 
  160 
  161         if(file->cpus > 1)
  162         {
  163             codec->param.i_threads = file->cpus;
  164         }
  165 
  166         codec->encoder[current_field] = x264_encoder_open(&codec->param);
  167         codec->pic[current_field] = calloc(1, sizeof(x264_picture_t));
  168 //printf("encode 1 %d %d\n", codec->param.i_width, codec->param.i_height);
  169         x264_picture_alloc(codec->pic[current_field], 
  170             X264_CSP_I420, 
  171             codec->param.i_width, 
  172             codec->param.i_height);
  173     }
  174 
  175 
  176 
  177 
  178 
  179 
  180     codec->pic[current_field]->i_type = X264_TYPE_AUTO;
  181     codec->pic[current_field]->i_qpplus1 = 0;
  182 
  183 
  184     if(codec->header_only)
  185     {
  186         bzero(codec->pic[current_field]->img.plane[0], w_16 * h_16);
  187         bzero(codec->pic[current_field]->img.plane[1], w_16 * h_16 / 4);
  188         bzero(codec->pic[current_field]->img.plane[2], w_16 * h_16 / 4);
  189     }
  190     else
  191     if(file->color_model == BC_YUV420P)
  192     {
  193         memcpy(codec->pic[current_field]->img.plane[0], row_pointers[0], w_16 * h_16);
  194         memcpy(codec->pic[current_field]->img.plane[1], row_pointers[1], w_16 * h_16 / 4);
  195         memcpy(codec->pic[current_field]->img.plane[2], row_pointers[2], w_16 * h_16 / 4);
  196     }
  197     else
  198     {
  199 //printf("encode 2 %p %p %p\n", codec->pic[current_field]->img.plane[0], codec->pic[current_field]->img.plane[1], codec->pic[current_field]->img.plane[2]);
  200         cmodel_transfer(0, /* Leave NULL if non existent */
  201             row_pointers,
  202             codec->pic[current_field]->img.plane[0], /* Leave NULL if non existent */
  203             codec->pic[current_field]->img.plane[1],
  204             codec->pic[current_field]->img.plane[2],
  205             row_pointers[0], /* Leave NULL if non existent */
  206             row_pointers[1],
  207             row_pointers[2],
  208             0,        /* Dimensions to capture from input frame */
  209             0, 
  210             width, 
  211             height,
  212             0,       /* Dimensions to project on output frame */
  213             0, 
  214             width, 
  215             height,
  216             file->color_model, 
  217             BC_YUV420P,
  218             0,         /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
  219             width,       /* For planar use the luma rowspan */
  220             codec->pic[current_field]->img.i_stride[0]);
  221         
  222     }
  223 
  224 
  225 
  226 
  227 
  228 
  229 
  230 
  231 
  232 
  233 
  234 
  235     x264_picture_t pic_out;
  236     x264_nal_t *nals;
  237     int nnal = 0;
  238     do
  239     {
  240         x264_encoder_encode(codec->encoder[current_field], 
  241             &nals, 
  242             &nnal, 
  243             codec->pic[current_field], 
  244             &pic_out);
  245 //printf("encode %d nnal=%d\n", __LINE__, nnal);
  246     } while(codec->header_only && !nnal);
  247     int allocation = w_16 * h_16 * 3;
  248     if(!codec->work_buffer)
  249     {
  250         codec->work_buffer = calloc(1, allocation);
  251     }
  252 
  253     codec->buffer_size = 0;
  254 //printf("encode %d nnal=%d\n", __LINE__, nnal);
  255     for(i = 0; i < nnal; i++)
  256     {
  257         int size_return = 0;
  258         int size = x264_nal_encode(codec->work_buffer + codec->buffer_size, 
  259             &size_return, 
  260             1, 
  261             nals + i);
  262         unsigned char *ptr = codec->work_buffer + codec->buffer_size;
  263 
  264 //printf("encode %d size=%d\n", __LINE__, size);
  265         if(size > 0)
  266         {
  267             if(size + codec->buffer_size > allocation)
  268             {
  269                 printf("qth264.c %d: overflow size=%d allocation=%d\n",
  270                     __LINE__,
  271                     size,
  272                     allocation);
  273             }
  274 
  275 // Size of NAL for avc
  276             uint64_t avc_size = size - 4;
  277 
  278 // Synthesize header.
  279 // Hopefully all the parameter set NAL's are present in the first frame.
  280             if(!avcc->data_size)
  281             {
  282                 if(header_size < 6)
  283                 {
  284                     header[header_size++] = 0x01;
  285                     header[header_size++] = 0x4d;
  286                     header[header_size++] = 0x40;
  287                     header[header_size++] = 0x1f;
  288                     header[header_size++] = 0xff;
  289                     header[header_size++] = 0xe1;
  290                 }
  291 
  292                 int nal_type = (ptr[4] & 0x1f);
  293 // Picture parameter or sequence parameter set
  294                 if(nal_type == 0x7 && !got_sps)
  295                 {
  296                     got_sps = 1;
  297                     header[header_size++] = (avc_size & 0xff00) >> 8;
  298                     header[header_size++] = (avc_size & 0xff);
  299                     memcpy(&header[header_size], 
  300                         ptr + 4,
  301                         avc_size);
  302                     header_size += avc_size;
  303                 }
  304                 else
  305                 if(nal_type == 0x8 && !got_pps)
  306                 {
  307                     got_pps = 1;
  308 // Number of sps nal's.
  309                     header[header_size++] = 0x1;
  310                     header[header_size++] = (avc_size & 0xff00) >> 8;
  311                     header[header_size++] = (avc_size & 0xff);
  312                     memcpy(&header[header_size], 
  313                         ptr + 4,
  314                         avc_size);
  315                     header_size += avc_size;
  316                 }
  317 
  318 // Write header
  319                 if(got_sps && got_pps)
  320                 {
  321                     quicktime_set_avcc_header(avcc,
  322                         header, 
  323                         header_size);
  324                 }
  325             }
  326 
  327 
  328 // Convert to avc nal
  329             *ptr++ = (avc_size & 0xff000000) >> 24;
  330             *ptr++ = (avc_size & 0xff0000) >> 16;
  331             *ptr++ = (avc_size & 0xff00) >> 8;
  332             *ptr++ = (avc_size & 0xff);
  333             codec->buffer_size += size;
  334         }
  335         else
  336             break;
  337     }
  338 
  339     pthread_mutex_unlock(&h264_lock);
  340 
  341 
  342 
  343     if(!codec->header_only)
  344     {
  345         if(pic_out.i_type == X264_TYPE_IDR ||
  346             pic_out.i_type == X264_TYPE_I)
  347         {
  348             is_keyframe = 1;
  349         }
  350 
  351         if(codec->buffer_size)
  352         {
  353             quicktime_write_chunk_header(file, trak, &chunk_atom);
  354             result = !quicktime_write_data(file, 
  355                 codec->work_buffer, 
  356                 codec->buffer_size);
  357             quicktime_write_chunk_footer(file, 
  358                 trak,
  359                 vtrack->current_chunk,
  360                 &chunk_atom, 
  361                 1);
  362         }
  363 
  364         if(is_keyframe)
  365         {
  366             quicktime_insert_keyframe(file, 
  367                 vtrack->current_position, 
  368                 track);
  369         }
  370         vtrack->current_chunk++;
  371     }
  372     return result;
  373 }
  374 
  375 
  376 
  377 
  378 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
  379 {
  380     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  381     quicktime_trak_t *trak = vtrack->track;
  382     quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  383     quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
  384     int width = trak->tkhd.track_width;
  385     int height = trak->tkhd.track_height;
  386     int w_16 = quicktime_quantize16(width);
  387     int h_16 = quicktime_quantize16(height);
  388 
  389 
  390     if(!codec->decoder) codec->decoder = quicktime_new_ffmpeg(
  391         file->cpus,
  392         codec->total_fields,
  393         CODEC_ID_H264,
  394         width,
  395         height,
  396         stsd_table);
  397     
  398 
  399     if(codec->decoder) return quicktime_ffmpeg_decode(codec->decoder,
  400         file, 
  401         row_pointers, 
  402         track);
  403 
  404     return 1;
  405 }
  406 
  407 // Header copied straight out of another h264 file
  408 #ifdef MANUAL_HEADER
  409 static int write_avcc_header(unsigned char *data)
  410 {
  411     int result = 0;
  412     unsigned char *ptr = data;
  413 
  414 
  415     static unsigned char test[] =
  416     {
  417         0x01, 0x4d, 0x40, 0x1f, 0xff, 0xe1, 0x00, 0x14,
  418         0x27, 0x4d, 0x40, 0x1f, 0xa9, 0x18, 0x0a, 0x00, 
  419         0xb7, 0x60, 0x0d, 0x40, 0x40, 0x40, 0x4c, 0x2b, 
  420         0x5e, 0xf7, 0xc0, 0x40, 0x01, 0x00, 0x04, 0x28, 
  421         0xce, 0x0f, 0x88
  422     };
  423 
  424     memcpy(data, test, sizeof(test));
  425     result = sizeof(test);
  426 
  427     return result;
  428 }
  429 #endif
  430 
  431 static void flush(quicktime_t *file, int track)
  432 {
  433     quicktime_video_map_t *track_map = &(file->vtracks[track]);
  434     quicktime_trak_t *trak = track_map->track;
  435     quicktime_h264_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
  436     quicktime_avcc_t *avcc = &trak->mdia.minf.stbl.stsd.table[0].avcc;
  437 
  438     if(!avcc->data_size)
  439     {
  440 
  441 #ifndef MANUAL_HEADER
  442         codec->header_only = 1;
  443         encode(file, 0, track);
  444 #else
  445         unsigned char temp[1024];
  446         int size = write_avcc_header(temp);
  447         if(size)
  448             quicktime_set_avcc_header(avcc,
  449                 temp, 
  450                 size);
  451 #endif
  452 
  453     }
  454 /*
  455  *  trak->mdia.minf.stbl.stsd.table[0].version = 1;
  456  *  trak->mdia.minf.stbl.stsd.table[0].revision = 1;
  457  */
  458 }
  459 
  460 
  461 
  462 static int reads_colormodel(quicktime_t *file, 
  463         int colormodel, 
  464         int track)
  465 {
  466     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  467     quicktime_codec_t *codec = (quicktime_codec_t*)vtrack->codec;
  468     return (colormodel == BC_YUV420P);
  469 }
  470 
  471 static int writes_colormodel(quicktime_t *file, 
  472         int colormodel, 
  473         int track)
  474 {
  475     return (colormodel == BC_YUV420P);
  476 }
  477 
  478 static int set_parameter(quicktime_t *file, 
  479         int track, 
  480         char *key, 
  481         void *value)
  482 {
  483     quicktime_video_map_t *vtrack = &(file->vtracks[track]);
  484     char *compressor = quicktime_compressor(vtrack->track);
  485 
  486     if(quicktime_match_32(compressor, QUICKTIME_H264) ||
  487         quicktime_match_32(compressor, QUICKTIME_HV64))
  488     {
  489         quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
  490         if(!strcasecmp(key, "h264_bitrate"))
  491         {
  492             if(quicktime_match_32(compressor, QUICKTIME_H264))
  493                 codec->param.rc.i_bitrate = *(int*)value;
  494             else
  495                 codec->param.rc.i_bitrate = *(int*)value / 2;
  496         }
  497         else
  498         if(!strcasecmp(key, "h264_quantizer"))
  499         {
  500             codec->param.rc.i_qp_constant = 
  501                 codec->param.rc.i_qp_min = 
  502                 codec->param.rc.i_qp_max = *(int*)value;
  503         }
  504         else
  505         if(!strcasecmp(key, "h264_fix_bitrate"))
  506 #ifdef GOOD_VERSION
  507             codec->param.rc.b_cbr = (*(int*)value) / 1000;
  508 #else
  509             codec->param.rc.i_qp_constant = (*(int*)value) / 1000;
  510 #endif
  511     }
  512 }
  513 
  514 static quicktime_h264_codec_t* init_common(quicktime_video_map_t *vtrack, 
  515     char *compressor,
  516     char *title,
  517     char *description)
  518 {
  519     quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
  520     quicktime_h264_codec_t *codec;
  521 
  522     codec_base->priv = calloc(1, sizeof(quicktime_h264_codec_t));
  523     codec_base->delete_vcodec = delete_codec;
  524     codec_base->decode_video = decode;
  525     codec_base->encode_video = encode;
  526     codec_base->flush = flush;
  527     codec_base->reads_colormodel = reads_colormodel;
  528     codec_base->writes_colormodel = writes_colormodel;
  529     codec_base->set_parameter = set_parameter;
  530     codec_base->fourcc = compressor;
  531     codec_base->title = title;
  532     codec_base->desc = description;
  533 
  534 
  535     codec = (quicktime_h264_codec_t*)codec_base->priv;
  536     x264_param_default(&codec->param);
  537 
  538     return codec;
  539 }
  540 
  541 
  542 void quicktime_init_codec_h264(quicktime_video_map_t *vtrack)
  543 {
  544     quicktime_h264_codec_t *result = init_common(vtrack,
  545         QUICKTIME_H264,
  546         "H.264",
  547         "H.264");
  548     result->total_fields = 1;
  549 }
  550 
  551 
  552 // field based H.264
  553 void quicktime_init_codec_hv64(quicktime_video_map_t *vtrack)
  554 {
  555     quicktime_h264_codec_t *result = init_common(vtrack, 
  556         QUICKTIME_HV64,
  557         "Dual H.264",
  558         "H.264 with two streams alternating every other frame.  (Not standardized)");
  559     result->total_fields = 2;
  560 }
  561