⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libmjpeg.c

📁 这个库实现了录象功能
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************* libmjpeg.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ #include "lqt_private.h"#include "libmjpeg.h"#include <quicktime/colormodels.h>#include <stdlib.h>#include <string.h>#include <strings.h>#define LOG_DOMAIN "libmjpeg"/* JPEG MARKERS */#define   M_SOF0    0xc0#define   M_SOF1    0xc1#define   M_SOF2    0xc2#define   M_SOF3    0xc3#define   M_SOF5    0xc5#define   M_SOF6    0xc6#define   M_SOF7    0xc7#define   M_JPG     0xc8#define   M_SOF9    0xc9#define   M_SOF10   0xca#define   M_SOF11   0xcb#define   M_SOF13   0xcd#define   M_SOF14   0xce#define   M_SOF15   0xcf#define   M_DHT     0xc4#define   M_DAC     0xcc#define   M_RST0    0xd0#define   M_RST1    0xd1#define   M_RST2    0xd2#define   M_RST3    0xd3#define   M_RST4    0xd4#define   M_RST5    0xd5#define   M_RST6    0xd6#define   M_RST7    0xd7#define   M_SOI     0xd8#define   M_EOI     0xd9#define   M_SOS     0xda#define   M_DQT     0xdb#define   M_DNL     0xdc#define   M_DRI     0xdd#define   M_DHP     0xde#define   M_EXP     0xdf#define   M_APP0    0xe0#define   M_APP1    0xe1#define   M_APP2    0xe2#define   M_APP3    0xe3#define   M_APP4    0xe4#define   M_APP5    0xe5#define   M_APP6    0xe6#define   M_APP7    0xe7#define   M_APP8    0xe8#define   M_APP9    0xe9#define   M_APP10   0xea#define   M_APP11   0xeb#define   M_APP12   0xec#define   M_APP13   0xed#define   M_APP14   0xee#define   M_APP15   0xef#define   M_JPG0    0xf0#define   M_JPG13   0xfd#define   M_COM     0xfe#define   M_TEM     0x01#define   M_ERROR   0x100#define QUICKTIME_MARKER_SIZE 0x2c#define QUICKTIME_JPEG_TAG 0x6d6a7067METHODDEF(void) mjpeg_error_exit (j_common_ptr cinfo)  {  /* cinfo->err really points to a mjpeg_error_mgr struct, so coerce pointer */  mjpeg_error_ptr mjpegerr = (mjpeg_error_ptr) cinfo->err;  /* Always display the message. */  /* We could postpone this until after returning, if we chose. */  (*cinfo->err->output_message) (cinfo);  /* Return control to the setjmp point */  longjmp(mjpegerr->setjmp_buffer, 1);  }typedef struct   {  struct jpeg_destination_mgr pub; /* public fields */  JOCTET *buffer;		/* Pointer to buffer */  mjpeg_compressor *engine;  } mjpeg_destination_mgr;typedef mjpeg_destination_mgr *mjpeg_dest_ptr;/* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. */METHODDEF(void) init_destination(j_compress_ptr cinfo)  {  mjpeg_dest_ptr dest = (mjpeg_dest_ptr)cinfo->dest;  /* Set the pointer to the preallocated buffer */  if(!dest->engine->output_buffer)    {    dest->engine->output_buffer = lqt_bufalloc(65536);    dest->engine->output_allocated = 65536;    }  dest->buffer = dest->engine->output_buffer;  dest->pub.next_output_byte = dest->engine->output_buffer;  dest->pub.free_in_buffer = dest->engine->output_allocated;  }/* * Empty the output buffer --- called whenever buffer fills up. * * In typical applications, this should write the entire output buffer * (ignoring the current state of next_output_byte & free_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been dumped. * * In applications that need to be able to suspend compression due to output * overrun, a FALSE return indicates that the buffer cannot be emptied now. * In this situation, the compressor will return to its caller (possibly with * an indication that it has not accepted all the supplied scanlines).  The * application should resume compression after it has made more room in the * output buffer.  Note that there are substantial restrictions on the use of * suspension --- see the documentation. * * When suspending, the compressor will back up to a convenient restart point * (typically the start of the current MCU). next_output_byte & free_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point will be regenerated after resumption, so do not * write it out when emptying the buffer externally. */METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo)  {  /* Allocate a bigger buffer. */  mjpeg_dest_ptr dest = (mjpeg_dest_ptr)cinfo->dest;  dest->engine->output_size = dest->engine->output_allocated;  dest->engine->output_allocated *= 2;  dest->engine->output_buffer = realloc(dest->engine->output_buffer,                                         dest->engine->output_allocated);  dest->buffer = dest->engine->output_buffer;  dest->pub.next_output_byte = dest->buffer + dest->engine->output_size;  dest->pub.free_in_buffer = dest->engine->output_allocated - dest->engine->output_size;  return TRUE;  }/* * Terminate destination --- called by jpeg_finish_compress * after all data has been written.  Usually needs to flush buffer. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */METHODDEF(void) term_destination(j_compress_ptr cinfo)  {  /* Just get the length */  mjpeg_dest_ptr dest = (mjpeg_dest_ptr)cinfo->dest;  dest->engine->output_size = dest->engine->output_allocated - dest->pub.free_in_buffer;  }static GLOBAL(void) jpeg_buffer_dest(j_compress_ptr cinfo, mjpeg_compressor *engine)  {  mjpeg_dest_ptr dest;  /* The destination object is made permanent so that multiple JPEG images   * can be written to the same file without re-executing jpeg_stdio_dest.   * This makes it dangerous to use this manager and a different destination   * manager serially with the same JPEG object, because their private object   * sizes may be different.  Caveat programmer.   */  if(cinfo->dest == NULL)     {	    /* first time for this JPEG object? */    cinfo->dest = (struct jpeg_destination_mgr *)      (*cinfo->mem->alloc_small)((j_common_ptr)cinfo,                                  JPOOL_PERMANENT,                                 sizeof(mjpeg_destination_mgr));    }  dest = (mjpeg_dest_ptr)cinfo->dest;  dest->pub.init_destination = init_destination;  dest->pub.empty_output_buffer = empty_output_buffer;  dest->pub.term_destination = term_destination;  dest->engine = engine;  }typedef struct {struct jpeg_source_mgr pub;	/* public fields */JOCTET * buffer;		/* start of buffer */int bytes;             /* total size of buffer */  } mjpeg_source_mgr;typedef mjpeg_source_mgr* mjpeg_src_ptr;METHODDEF(void) init_source(j_decompress_ptr cinfo)  {  }METHODDEF(boolean) fill_input_buffer(j_decompress_ptr cinfo)  {  mjpeg_src_ptr src = (mjpeg_src_ptr) cinfo->src;  src->buffer[0] = (JOCTET)0xFF;  src->buffer[1] = (JOCTET)M_EOI;  src->pub.next_input_byte = src->buffer;  src->pub.bytes_in_buffer = 2;    return TRUE;  }METHODDEF(void) skip_input_data(j_decompress_ptr cinfo, long num_bytes)  {  mjpeg_src_ptr src = (mjpeg_src_ptr)cinfo->src;  src->pub.next_input_byte += (size_t)num_bytes;  src->pub.bytes_in_buffer -= (size_t)num_bytes;  }METHODDEF(void) term_source(j_decompress_ptr cinfo)  {  }static GLOBAL(void) jpeg_buffer_src(j_decompress_ptr cinfo, unsigned char *buffer, long bytes)  {  mjpeg_src_ptr src;  /* first time for this JPEG object? */  if(cinfo->src == NULL)    {	    cinfo->src = (struct jpeg_source_mgr*)      (*cinfo->mem->alloc_small)((j_common_ptr)cinfo,                                  JPOOL_PERMANENT,                                 sizeof(mjpeg_source_mgr));    src = (mjpeg_src_ptr)cinfo->src;    }  src = (mjpeg_src_ptr)cinfo->src;  src->pub.init_source = init_source;  src->pub.fill_input_buffer = fill_input_buffer;  src->pub.skip_input_data = skip_input_data;  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */  src->pub.term_source = term_source;  src->pub.bytes_in_buffer = bytes;  src->pub.next_input_byte = buffer;  src->buffer = buffer;  src->bytes = bytes;  }/* *  Buffer handling for variable size output buffers */static void reset_buffer(unsigned char **buffer, long *size, long *allocated)  {  *size = 0;  }static void delete_buffer(unsigned char **buffer, long *size, long *allocated)  {  if(*buffer)    {    free(*buffer);    *size = 0;    *allocated = 0;    }  }static void append_buffer(unsigned char **buffer,                           long *size,                           long *allocated,                          unsigned char *data,                          long data_size)  {  if(!*buffer)    {    *buffer = lqt_bufalloc(65536);    *size = 0;    *allocated = 65536;    }  if(*size + data_size > *allocated)    {    *allocated = *size + data_size;    *buffer = realloc(*buffer, *allocated);    }  memcpy(*buffer + *size, data, data_size);  *size += data_size;  }static void allocate_temps(mjpeg_t *mjpeg)  {  int i;    if(!mjpeg->temp_data)    {    switch(mjpeg->jpeg_color_model)      {      case BC_YUVJ422P:        mjpeg->temp_data = lqt_bufalloc(mjpeg->coded_w * mjpeg->coded_h * 2);        mjpeg->temp_rows[0] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        mjpeg->temp_rows[1] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        mjpeg->temp_rows[2] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        for(i = 0; i < mjpeg->coded_h; i++)          {          mjpeg->temp_rows[0][i] = mjpeg->temp_data + i * mjpeg->coded_w;          mjpeg->temp_rows[1][i] = mjpeg->temp_data + mjpeg->coded_w * mjpeg->coded_h + i * mjpeg->coded_w / 2;          mjpeg->temp_rows[2][i] = mjpeg->temp_data + mjpeg->coded_w * mjpeg->coded_h + mjpeg->coded_w / 2 * mjpeg->coded_h + i * mjpeg->coded_w / 2;          }        break;              case BC_YUVJ444P:        mjpeg->temp_data = lqt_bufalloc(mjpeg->coded_w * mjpeg->coded_h * 3);        mjpeg->temp_rows[0] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        mjpeg->temp_rows[1] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        mjpeg->temp_rows[2] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        for(i = 0; i < mjpeg->coded_h; i++)          {          mjpeg->temp_rows[0][i] = mjpeg->temp_data + i * mjpeg->coded_w;          mjpeg->temp_rows[1][i] = mjpeg->temp_data + mjpeg->coded_w * mjpeg->coded_h + i * mjpeg->coded_w;          mjpeg->temp_rows[2][i] = mjpeg->temp_data + mjpeg->coded_w * mjpeg->coded_h + mjpeg->coded_w * mjpeg->coded_h + i * mjpeg->coded_w;          }        break;              case BC_YUVJ420P:        mjpeg->temp_data = lqt_bufalloc(mjpeg->coded_w * mjpeg->coded_h + mjpeg->coded_w * mjpeg->coded_h / 2);        mjpeg->temp_rows[0] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        mjpeg->temp_rows[1] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h / 2);        mjpeg->temp_rows[2] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h / 2);        for(i = 0; i < mjpeg->coded_h; i++)          {          mjpeg->temp_rows[0][i] = mjpeg->temp_data + i * mjpeg->coded_w;          if(i < mjpeg->coded_h / 2)            {            mjpeg->temp_rows[1][i] = mjpeg->temp_data + mjpeg->coded_w * mjpeg->coded_h + i * (mjpeg->coded_w / 2);            mjpeg->temp_rows[2][i] = mjpeg->temp_data + mjpeg->coded_w * mjpeg->coded_h + (mjpeg->coded_h / 2) * (mjpeg->coded_w / 2) + i * (mjpeg->coded_w / 2);            }          }        break;      }    }  }static int get_input_row(mjpeg_t *mjpeg, int i, int field)  {  int input_row;  if(mjpeg->fields > 1)     input_row = i * 2 + field;  else    input_row = i;  if(input_row >= mjpeg->coded_h) input_row = mjpeg->coded_h - 1;  return input_row;  }// Get pointers to rows for the JPEG compressorstatic void get_rows(mjpeg_t *mjpeg, mjpeg_compressor *compressor, int field)  {  int i;  if((mjpeg->fields > 1) && (mjpeg->bottom_first))    field = 1 - field;      switch(mjpeg->jpeg_color_model)    {    case BC_YUVJ444P:      {      if(!compressor->rows[0])        {        compressor->rows[0] = lqt_bufalloc(sizeof(unsigned char*) * compressor->field_h);        compressor->rows[1] = lqt_bufalloc(sizeof(unsigned char*) * compressor->field_h);        compressor->rows[2] = lqt_bufalloc(sizeof(unsigned char*) * compressor->field_h);        }      for(i = 0; i < compressor->field_h; i++)        {        int input_row = get_input_row(mjpeg, i, field);        compressor->rows[0][i] = mjpeg->temp_rows[0][input_row];        compressor->rows[1][i] = mjpeg->temp_rows[1][input_row];        compressor->rows[2][i] = mjpeg->temp_rows[2][input_row];        }      break;      }    case BC_YUVJ422P:      {      if(!compressor->rows[0])        {        compressor->rows[0] = lqt_bufalloc(sizeof(unsigned char*) * compressor->field_h);        compressor->rows[1] = lqt_bufalloc(sizeof(unsigned char*) * compressor->field_h);        compressor->rows[2] = lqt_bufalloc(sizeof(unsigned char*) * compressor->field_h);        }      for(i = 0; i < compressor->field_h; i++)        {        int input_row = get_input_row(mjpeg, i, field);        compressor->rows[0][i] = mjpeg->temp_rows[0][input_row];        compressor->rows[1][i] = mjpeg->temp_rows[1][input_row];        compressor->rows[2][i] = mjpeg->temp_rows[2][input_row];        }      break;      }    case BC_YUVJ420P:      {      if(!compressor->rows[0])        {        compressor->rows[0] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h);        compressor->rows[1] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h / 2);        compressor->rows[2] = lqt_bufalloc(sizeof(unsigned char*) * mjpeg->coded_h / 2);        }      for(i = 0; i < compressor->field_h; i++)        {        int input_row = get_input_row(mjpeg, i, field);        compressor->rows[0][i] = mjpeg->temp_rows[0][input_row];        if(i < compressor->field_h / 2)          {          compressor->rows[1][i] = mjpeg->temp_rows[1][input_row];          compressor->rows[2][i] = mjpeg->temp_rows[2][input_row];          }        }      break;      }    }  }static void delete_rows(mjpeg_compressor *compressor)  {  if(compressor->rows[0])    {    free(compressor->rows[0]);    free(compressor->rows[1]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -