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

📄 lav_io.c

📁 Motion JPEG编解码器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Some routines for handling I/O from/to different video *  file formats (currently AVI, Quicktime) * *  These routines are isolated here in an extra file *  in order to be able to handle more formats in the future. * *  Copyright (C) 2000 Rainer Johanni <Rainer@Johanni.de> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program 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 General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <config.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#define COMPILE_LAV_IO_C#include "lav_io.h"#ifdef HAVE_LIBDV#include <libdv/dv.h>#endif#ifdef HAVE_LIBQUICKTIME#include <quicktime.h>#include <lqt.h>#endifextern int AVI_errno;static char video_format=' ';static int  internal_error=0;#define ERROR_JPEG      1#define ERROR_MALLOC    2#define ERROR_FORMAT    3#define ERROR_NOAUDIO   4static unsigned long jpeg_field_size     = 0;static unsigned long jpeg_quant_offset   = 0;static unsigned long jpeg_huffman_offset = 0;static unsigned long jpeg_image_offset   = 0;static unsigned long jpeg_scan_offset    = 0;static unsigned long jpeg_data_offset    = 0;static unsigned long jpeg_padded_len     = 0;static unsigned long jpeg_app0_offset    = 0;static unsigned long jpeg_app1_offset    = 0;#define M_SOF0  0xC0#define M_SOF1  0xC1#define M_DHT   0xC4#define M_SOI   0xD8		/* Start Of Image (beginning of datastream) */#define M_EOI   0xD9		/* End Of Image (end of datastream) */#define M_SOS   0xDA		/* Start Of Scan (begins compressed data) */#define M_DQT   0xDB#define M_APP0  0xE0#define M_APP1  0xE1#define QUICKTIME_MJPG_TAG 0x6d6a7067  /* 'mjpg' */static int check_YUV420_input(lav_file_t *lav_fd);#ifdef HAVE_LIBDVstatic int check_DV2_input(lav_file_t *lav_fd);#endif#define TMP_EXTENSION ".tmp"#ifdef HAVE_LIBQUICKTIME/*   put_int4:   Put a 4 byte integer value into a character array as big endian number*/static void put_int4(unsigned char *buf, int val){	buf[0] = (val >> 24);	buf[1] = (val >> 16);	buf[2] = (val >> 8 );	buf[3] = (val      );}#endif/*   get_int2:   get a 2 byte integer value from a character array as big endian number */static int get_int2(unsigned char *buff){   return (buff[0]*256 + buff[1]);}/*   scan_jpeg:   Scan jpeg data for markers, needed for Quicktime MJPA format   and partly for AVI files.   Taken mostly from Adam Williams' quicktime library */static int scan_jpeg(unsigned char * jpegdata, long jpeglen, int header_only){   int  marker, length;   long p;   jpeg_field_size     = 0;   jpeg_quant_offset   = 0;   jpeg_huffman_offset = 0;   jpeg_image_offset   = 0;   jpeg_scan_offset    = 0;   jpeg_data_offset    = 0;   jpeg_padded_len     = 0;   jpeg_app0_offset    = 0;   jpeg_app1_offset    = 0;   /* The initial marker must be SOI */   if (jpegdata[0] != 0xFF || jpegdata[1] != M_SOI) return -1;   /* p is the pointer within the jpeg data */   p = 2;   /* scan through the jpeg data */   while(p<jpeglen)   {      /* get next marker */      /* Find 0xFF byte; skip any non-FFs */      while(jpegdata[p] != 0xFF)      {         p++;         if(p>=jpeglen) return -1;      }      /* Get marker code byte, swallowing any duplicate FF bytes */      while(jpegdata[p] == 0xFF)      {         p++;         if(p>=jpeglen) return -1;      }      marker = jpegdata[p++];      if(p<=jpeglen-2)         length = get_int2(jpegdata+p);      else         length = 0;      /* We found a marker - check it */      if(marker == M_EOI) { jpeg_field_size = p; break; }      switch(marker)      {         case M_SOF0:         case M_SOF1:            jpeg_image_offset = p-2;            break;         case M_DQT:            if(jpeg_quant_offset==0) jpeg_quant_offset = p-2;            break;         case M_DHT:            if(jpeg_huffman_offset==0) jpeg_huffman_offset = p-2;            break;         case M_SOS:            jpeg_scan_offset = p-2;            jpeg_data_offset = p+length;            if(header_only) return 0; /* we are done with the headers */            break;         case M_APP0:            if(jpeg_app0_offset==0) jpeg_app0_offset = p-2;            break;         case M_APP1:            if(jpeg_app1_offset==0) jpeg_app1_offset = p-2;            break;      }      /* The pseudo marker as well as the markers M_TEM (0x01)         and M_RST0 ... M_RST7 (0xd0 ... 0xd7) have no paramters.         M_SOI and M_EOI also have no parameters, but we should         never come here in that case */      if(marker == 0 || marker == 1 || (marker >= 0xd0 && marker <= 0xd7))         continue;      /* skip length bytes */      if(p+length<=jpeglen)         p += length;      else         return -1;   }   /* We are through parsing the jpeg data, we should have seen M_EOI */   if(!jpeg_field_size) return -1;   /* Check for trailing garbage until jpeglen is reached or a new      M_SOI is seen */   while(p<jpeglen)   {      if(p<jpeglen-1 && jpegdata[p]==0xFF && jpegdata[p+1]==M_SOI) break;      p++;   }   jpeg_padded_len = p;   return 0;}/* The query routines about the format */int lav_query_APP_marker(char format){   /* AVI needs the APP0 marker, Quicktime APP1 */   switch(format)   {      case 'a': return 0;      case 'A': return 0;      case 'j': return 0;      case 'q': return 1;      case 'm': return 0;      default:  return 0;   }}int lav_query_APP_length(char format){   /* AVI: APP0 14 bytes, Quicktime APP1: 40 */   switch(format)   {      case 'a': return 14;      case 'A': return 14;      case 'j': return 14;      case 'q': return 40;      case 'm': return 0;      default:  return 0;   }}int lav_query_polarity(char format){   /* Quicktime needs TOP_FIRST, for AVI we have the choice */   switch(format)   {      case 'a': return LAV_INTER_TOP_FIRST;      case 'A': return LAV_INTER_BOTTOM_FIRST;      case 'j': return LAV_INTER_TOP_FIRST;      case 'q': return LAV_INTER_TOP_FIRST;      case 'm': return LAV_INTER_TOP_FIRST;      default:  return LAV_INTER_TOP_FIRST;   }}lav_file_t *lav_open_output_file(char *filename, char format,                    int width, int height, int interlaced, double fps,                    int asize, int achans, long arate){   lav_file_t *lav_fd = (lav_file_t*) malloc(sizeof(lav_file_t));   char *extension, *tempfile;   if (lav_fd == 0) { internal_error=ERROR_MALLOC; return 0; }   /* Set lav_fd */   lav_fd->avi_fd      = 0;   lav_fd->qt_fd       = 0;   lav_fd->format      = format;   /* Sanity check: do not create a quicktime file that is named with .avi */   extension = rindex(filename, '.');   if (extension != NULL)   {      extension++;      switch(format)        {        case 'a':        case 'A':          if (strcmp(extension, "avi") && strcmp(extension, "AVI"))             {               internal_error = ERROR_FORMAT;               return 0;            }          break;        case 'q':          if (strcmp(extension,  "qt") && strcmp(extension,  "QT") &&              strcmp(extension, "mov") && strcmp(extension, "MOV") &&               strcmp(extension,"moov") && strcmp(extension,"MOOV"))             {             internal_error = ERROR_FORMAT;             return 0;            }          break;        case 'j':          if (strcmp(extension, "jpg") && strcmp(extension, "jpg") &&              strcmp(extension,"jpeg") && strcmp(extension,"JPEG"))            {              internal_error = ERROR_FORMAT;              return 0;            }          break;        }   }   lav_fd->interlacing = interlaced ? lav_query_polarity(format) :                                      LAV_NOT_INTERLACED;   lav_fd->has_audio   = (asize>0 && achans>0);   lav_fd->bps         = (asize*achans+7)/8;   lav_fd->MJPG_chroma = CHROMAUNKNOWN;   switch(format)   {      case 'a':      case 'A':         /* Open AVI output file */         lav_fd->avi_fd = AVI_open_output_file(filename);         if(!lav_fd->avi_fd) { free(lav_fd); return 0; }         AVI_set_video(lav_fd->avi_fd, width, height, fps, "MJPG");         if (asize) AVI_set_audio(lav_fd->avi_fd, achans, arate, asize, WAVE_FORMAT_PCM);         return lav_fd;      case 'j':        /* Open JPEG output file */	tempfile = (char *)malloc(strlen(filename) + strlen(TMP_EXTENSION) + 1);	if (tempfile == NULL)	   {	   internal_error=ERROR_MALLOC;	   return(0);	   }        strcpy(tempfile, filename);        strcat(tempfile, TMP_EXTENSION);        lav_fd->jpeg_filename = strdup(filename);        lav_fd->jpeg_fd = open(tempfile, O_CREAT | O_TRUNC | O_WRONLY, 0644);	free(tempfile);        return lav_fd;      case 'q':#ifdef HAVE_LIBQUICKTIME         /* open quicktime output file */         /* since the documentation says that the file should be empty,            we try to remove it first */         remove(filename);         lav_fd->qt_fd = quicktime_open(filename, 0, 1);         if(!lav_fd->qt_fd) { free(lav_fd); return 0; }         quicktime_set_video(lav_fd->qt_fd, 1, width, height, fps,                             (interlaced ? QUICKTIME_MJPA : QUICKTIME_JPEG));         if (asize)	    quicktime_set_audio(lav_fd->qt_fd, achans, arate, asize, QUICKTIME_TWOS);         return lav_fd;#else	 internal_error = ERROR_FORMAT;	 return 0;#endif      default:         return 0;   }}int lav_close(lav_file_t *lav_file)   {   int res;   char *tempfile;   video_format = lav_file->format; internal_error = 0; /* for error messages */   switch (lav_file->format)      {      case 'a':      case 'A':         res = AVI_close( lav_file->avi_fd );         break;      case 'j':	 tempfile = (char *)malloc(strlen(lav_file->jpeg_filename) + 				   strlen(TMP_EXTENSION) + 1);	 if (tempfile == NULL)	    {	    res = -1;	    break;	    }         strcpy(tempfile, lav_file->jpeg_filename);         strcat(tempfile, TMP_EXTENSION);         res = close(lav_file->jpeg_fd);         rename(tempfile, lav_file->jpeg_filename);	 free(tempfile);         free(lav_file->jpeg_filename);         break;#ifdef HAVE_LIBQUICKTIME      case 'q':         res = quicktime_close( lav_file->qt_fd );         break;#endif      default:         res = -1;      }   free(lav_file);   return res;   }int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count){   int res, n;   uint8_t *jpgdata = NULL;   long jpglen = 0;   video_format = lav_file->format; internal_error = 0; /* for error messages */   /* For interlaced video insert the apropriate APPn markers */   if(lav_file->interlacing!=LAV_NOT_INTERLACED)   {      switch(lav_file->format)      {         case 'a':         case 'A':            jpgdata = buff;            jpglen  = size;            /* Loop over both fields */            for(n=0;n<2;n++)            {               /* For first field scan entire field, for second field                  scan the JPEG header, put in AVI1 + polarity.                  Be generous on errors */

⌨️ 快捷键说明

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