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

📄 dv.c

📁 FFmpeg is an audio/video conversion tool. It includes libavcodec, the leading open source codec libr
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * General DV muxer/demuxer  * Copyright (c) 2003 Roman Shaposhnick * * Many thanks to Dan Dennedy <dan@dennedy.org> for providing wealth * of DV technical info. * * Raw DV format * Copyright (c) 2002 Fabrice Bellard. * * 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <time.h>#include "avformat.h"#include "dvdata.h"#include "dv.h"struct DVDemuxContext {    AVFormatContext* fctx;    AVStream*        vst;    AVStream*        ast[2];           AVPacket         audio_pkt[2];    int              ach;    int              frames;    uint64_t         abytes;};struct DVMuxContext {    const DVprofile*  sys;    /* Current DV profile. E.g.: 525/60, 625/50 */    uint8_t     frame_buf[144000]; /* frame under contruction */    FifoBuffer  audio_data;   /* Fifo for storing excessive amounts of PCM */    int         frames;       /* Number of a current frame */    time_t      start_time;   /* Start time of recording */    uint8_t     aspect;       /* Aspect ID 0 - 4:3, 7 - 16:9 */    int         has_audio;    /* frame under contruction has audio */    int         has_video;    /* frame under contruction has video */};enum dv_section_type {     dv_sect_header  = 0x1f,     dv_sect_subcode = 0x3f,     dv_sect_vaux    = 0x56,     dv_sect_audio   = 0x76,     dv_sect_video   = 0x96,};enum dv_pack_type {     dv_header525     = 0x3f, /* see dv_write_pack for important details on */      dv_header625     = 0xbf, /* these two packs */     dv_timecode      = 0x13,     dv_audio_source  = 0x50,     dv_audio_control = 0x51,     dv_audio_recdate = 0x52,     dv_audio_rectime = 0x53,     dv_video_source  = 0x60,     dv_video_control = 0x61,     dv_viedo_recdate = 0x62,     dv_video_rectime = 0x63,     dv_unknown_pack  = 0xff,};/* * The reason why the following three big ugly looking tables are * here is my lack of DV spec IEC 61834. The tables were basically  * constructed to make code that places packs in SSYB, VAUX and  * AAUX blocks very simple and table-driven. They conform to the * SMPTE 314M and the output of my personal DV camcorder, neither * of which is sufficient for a reliable DV stream producing. Thus * while code is still in development I'll be gathering input from * people with different DV equipment and modifying the tables to * accommodate all the quirks. Later on, if possible, some of them * will be folded into smaller tables and/or switch-if logic. For  * now, my only excuse is -- they don't eat up that much of a space. */static const int dv_ssyb_packs_dist[12][6] = {    { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },    { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },    { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },    { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },    { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },    { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },    { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },    { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },    { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },    { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },    { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },    { 0x13, 0x62, 0x63, 0x13, 0x62, 0x63 },};static const int dv_vaux_packs_dist[12][15] = {    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },    { 0x60, 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,       0x60, 0x61, 0x62, 0x63, 0xff, 0xff },};static const int dv_aaux_packs_dist[12][9] = {    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },    { 0xff, 0xff, 0xff, 0x50, 0x51, 0x52, 0x53, 0xff, 0xff },    { 0x50, 0x51, 0x52, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff },};static inline uint16_t dv_audio_12to16(uint16_t sample){    uint16_t shift, result;        sample = (sample < 0x800) ? sample : sample | 0xf000;    shift = (sample & 0xf00) >> 8;    if (shift < 0x2 || shift > 0xd) {	result = sample;    } else if (shift < 0x8) {        shift--;	result = (sample - (256 * shift)) << shift;    } else {	shift = 0xe - shift;	result = ((sample + ((256 * shift) + 1)) << shift) - 1;    }    return result;}static int dv_audio_frame_size(const DVprofile* sys, int frame){    return sys->audio_samples_dist[frame % (sizeof(sys->audio_samples_dist)/		                            sizeof(sys->audio_samples_dist[0]))];}static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* buf){    struct tm tc;    time_t ct;    int ltc_frame;    buf[0] = (uint8_t)pack_id;    switch (pack_id) {    case dv_header525: /* I can't imagine why these two weren't defined as real */    case dv_header625: /* packs in SMPTE314M -- they definitely look like ones */          buf[1] = 0xf8 |               /* reserved -- always 1 */	           (0 & 0x07);          /* APT: Track application ID */          buf[2] = (0 << 7)    | /* TF1: audio data is 0 - valid; 1 - invalid */	           (0x0f << 3) | /* reserved -- always 1 */		   (0 & 0x07);   /* AP1: Audio application ID */          buf[3] = (0 << 7)    | /* TF2: video data is 0 - valid; 1 - invalid */  	           (0x0f << 3) | /* reserved -- always 1 */		   (0 & 0x07);   /* AP2: Video application ID */          buf[4] = (0 << 7)    | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */ 	           (0x0f << 3) | /* reserved -- always 1 */		   (0 & 0x07);   /* AP3: Subcode application ID */	  break;    case dv_timecode:          ct = (time_t)(c->frames / ((float)c->sys->frame_rate /                                      (float)c->sys->frame_rate_base));          localtime_r(&ct, &tc);          /*            * LTC drop-frame frame counter drops two frames (0 and 1) every            * minute, unless it is exactly divisible by 10           */          ltc_frame = (c->frames + 2*ct/60 - 2*ct/600) % c->sys->ltc_divisor;	  buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */		   (1 << 6) | /* Drop frame timecode: 0 - nondrop; 1 - drop */		   ((ltc_frame / 10) << 4) | /* Tens of frames */		   (ltc_frame % 10);         /* Units of frames */	  buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */		   ((tc.tm_sec / 10) << 4) | /* Tens of seconds */		   (tc.tm_sec % 10);         /* Units of seconds */	  buf[3] = (1 << 7) | /* Binary group flag BGF0 */		   ((tc.tm_min / 10) << 4) | /* Tens of minutes */		   (tc.tm_min % 10);         /* Units of minutes */	  buf[4] = (1 << 7) | /* Binary group flag BGF2 */		   (1 << 6) | /* Binary group flag BGF1 */	           ((tc.tm_hour / 10) << 4) | /* Tens of hours */		   (tc.tm_hour % 10);         /* Units of hours */          break;    case dv_audio_source:  /* AAUX source pack */          buf[1] = (0 << 7) | /* locked mode       */                   (1 << 6) | /* reserved -- always 1 */	           (dv_audio_frame_size(c->sys, c->frames) -		    c->sys->audio_min_samples[0]);	                      /* # of samples      */          buf[2] = (0 << 7) | /* multi-stereo      */                   (0 << 5) | /* #of audio channels per block: 0 -- 1 channel */                   (0 << 4) | /* pair bit: 0 -- one pair of channels */	            0;        /* audio mode        */          buf[3] = (1 << 7) | /* res               */                   (1 << 6) | /* multi-language flag */	           (c->sys->dsf << 5) | /*  system: 60fields/50fields */	            0;        /* definition: 0 -- SD (525/625) */          buf[4] = (1 << 7) | /* emphasis: 1 -- off */                   (0 << 6) | /* emphasis time constant: 0 -- reserved */	           (0 << 3) | /* frequency: 0 -- 48Khz, 1 -- 44,1Khz, 2 -- 32Khz */                    0;        /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */			              break;    case dv_audio_control:          buf[1] = (0 << 6) | /* copy protection: 0 -- unrestricted */                   (1 << 4) | /* input source: 1 -- digital input */	           (3 << 2) | /* compression: 3 -- no information */	            0;        /* misc. info/SMPTE emphasis off */          buf[2] = (1 << 7) | /* recording start point: 1 -- no */                   (1 << 6) | /* recording end point: 1 -- no */	           (1 << 3) | /* recording mode: 1 -- original */	            7;                   buf[3] = (1 << 7) | /* direction: 1 -- forward */                    0x20;     /* speed */          buf[4] = (1 << 7) | /* reserved -- always 1 */                    0x7f;     /* genre category */	  break;    case dv_audio_recdate:    case dv_viedo_recdate:  /* VAUX recording date */          ct = c->start_time + (time_t)(c->frames / 	       ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));          localtime_r(&ct, &tc);	  buf[1] = 0xff; /* ds, tm, tens of time zone, units of time zone */	                 /* 0xff is very likely to be "unknown" */	  buf[2] = (3 << 6) | /* reserved -- always 1 */		   ((tc.tm_mday / 10) << 4) | /* Tens of day */		   (tc.tm_mday % 10);         /* Units of day */	  buf[3] = /* we set high 4 bits to 0, shouldn't we set them to week? */		   (tc.tm_mon % 10);         /* Units of month */	  buf[4] = (((tc.tm_year % 100) / 10) << 4) | /* Tens of year */		   (tc.tm_year % 10);                 /* Units of year */          break;    case dv_audio_rectime:  /* AAUX recording time */    case dv_video_rectime:  /* VAUX recording time */          ct = c->start_time + (time_t)(c->frames / 	       ((float)c->sys->frame_rate / (float)c->sys->frame_rate_base));          localtime_r(&ct, &tc);	  buf[1] = (3 << 6) | /* reserved -- always 1 */		   0x3f; /* tens of frame, units of frame: 0x3f - "unknown" ? */	  buf[2] = (1 << 7) | /* reserved -- always 1 */ 		   ((tc.tm_sec / 10) << 4) | /* Tens of seconds */		   (tc.tm_sec % 10);         /* Units of seconds */	  buf[3] = (1 << 7) | /* reserved -- always 1 */		   ((tc.tm_min / 10) << 4) | /* Tens of minutes */		   (tc.tm_min % 10);         /* Units of minutes */	  buf[4] = (3 << 6) | /* reserved -- always 1 */ 	           ((tc.tm_hour / 10) << 4) | /* Tens of hours */		   (tc.tm_hour % 10);         /* Units of hours */	  break;    case dv_video_source:	  buf[1] = 0xff; /* reserved -- always 1 */	  buf[2] = (1 << 7) | /* B/W: 0 - b/w, 1 - color */		   (1 << 6) | /* following CLF is valid - 0, invalid - 1 */		   (3 << 4) | /* CLF: color frames id (see ITU-R BT.470-4) */		   0xf; /* reserved -- always 1 */	  buf[3] = (3 << 6) | /* reserved -- always 1 */		   (c->sys->dsf << 5) | /*  system: 60fields/50fields */		   0; /* signal type video compression */	  buf[4] = 0xff; /* VISC: 0xff -- no information */          break;    case dv_video_control:	  buf[1] = (0 << 6) | /* Copy generation management (CGMS) 0 -- free */		   0x3f; /* reserved -- always 1 */	  buf[2] = 0xc8 | /* reserved -- always b11001xxx */		   c->aspect;	  buf[3] = (1 << 7) | /* Frame/field flag 1 -- frame, 0 -- field */		   (1 << 6) | /* First/second field flag 0 -- field 2, 1 -- field 1 */		   (1 << 5) | /* Frame change flag 0 -- same picture as before, 1 -- different */		   (1 << 4) | /* 1 - interlaced, 0 - noninterlaced */		   0xc; /* reserved -- always b1100 */	  buf[4] = 0xff; /* reserved -- always 1 */          break;    default:          buf[1] = buf[2] = buf[3] = buf[4] = 0xff;    }    return 5;}static inline int dv_write_dif_id(enum dv_section_type t, uint8_t seq_num,                                   uint8_t dif_num, uint8_t* buf){    buf[0] = (uint8_t)t;    /* Section type */

⌨️ 快捷键说明

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