diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 90d101813b..fa2952dc65 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -1069,6 +1069,130 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, return s->sys->frame_size; } + +static inline int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c, uint8_t* buf) +{ + /* + * Here's what SMPTE314M says about these two: + * (page 6) APTn, AP1n, AP2n, AP3n: These data shall be identical + * as track application IDs (APTn = 001, AP1n = + * 001, AP2n = 001, AP3n = 001), if the source signal + * comes from a digital VCR. If the signal source is + * unknown, all bits for these data shall be set to 1. + * (page 12) STYPE: STYPE defines a signal type of video signal + * 00000b = 4:1:1 compression + * 00100b = 4:2:2 compression + * XXXXXX = Reserved + * Now, I've got two problems with these statements: + * 1. it looks like APT == 111b should be a safe bet, but it isn't. + * It seems that for PAL as defined in IEC 61834 we have to set + * APT to 000 and for SMPTE314M to 001. + * 2. It is not at all clear what STYPE is used for 4:2:0 PAL + * compression scheme (if any). + */ + int apt = (c->sys->pix_fmt == PIX_FMT_YUV420P ? 0 : 1); + int stype = (c->sys->pix_fmt == PIX_FMT_YUV422P ? 4 : 0); + + uint8_t aspect = 0; + if((int)(av_q2d(c->avctx->sample_aspect_ratio) * c->avctx->width / c->avctx->height * 10) == 17) /* 16:9 */ + aspect = 0x02; + + 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 */ + (apt & 0x07); /* APT: Track application ID */ + buf[2] = (0 << 7) | /* TF1: audio data is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP1: Audio application ID */ + buf[3] = (0 << 7) | /* TF2: video data is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP2: Video application ID */ + buf[4] = (0 << 7) | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP3: Subcode application ID */ + 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 */ + stype; /* 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 */ + 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 void dv_format_frame(DVVideoContext* c, uint8_t* buf) +{ + int chan, i, j, k; + + for (chan = 0; chan < c->sys->n_difchan; chan++) { + for (i = 0; i < c->sys->difseg_size; i++) { + memset(buf, 0xff, 80 * 6); /* First 6 DIF blocks are for control data */ + + /* DV header: 1DIF */ + buf += dv_write_dif_id(dv_sect_header, chan, i, 0, buf); + buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf); + buf += 72; /* unused bytes */ + + /* DV subcode: 2DIFs */ + for (j = 0; j < 2; j++) { + buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf); + for (k = 0; k < 6; k++) + buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf) + 5; + buf += 29; /* unused bytes */ + } + + /* DV VAUX: 3DIFS */ + for (j = 0; j < 3; j++) { + buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf); + buf += dv_write_pack(dv_video_source, c, buf); + buf += dv_write_pack(dv_video_control, c, buf); + buf += 7*5; + buf += dv_write_pack(dv_video_source, c, buf); + buf += dv_write_pack(dv_video_control, c, buf); + buf += 4*5 + 2; /* unused bytes */ + } + + /* DV Audio/Video: 135 Video DIFs + 9 Audio DIFs */ + for (j = 0; j < 135; j++) { + if (j%15 == 0) { + memset(buf, 0xff, 80); + buf += dv_write_dif_id(dv_sect_audio, chan, i, j/15, buf); + buf += 77; /* audio control & shuffled PCM audio */ + } + buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf); + buf += 77; /* 1 video macro block: 1 bytes control + 4 * 14 bytes Y 8x8 data + 10 bytes Cr 8x8 data + 10 bytes Cb 8x8 data */ + } + } + } +} + + + static int dvvideo_encode_frame(AVCodecContext *c, uint8_t *buf, int buf_size, void *data) { @@ -1091,18 +1215,7 @@ static int dvvideo_encode_frame(AVCodecContext *c, uint8_t *buf, int buf_size, emms_c(); - /* Fill in just enough of the header for dv_frame_profile() to - return the correct result, so that the frame can be decoded - correctly. The rest of the metadata is filled in by the dvvideo - avformat. (this should probably change so that encode_frame() - fills in ALL of the metadata - e.g. for Quicktime-wrapped DV - streams) */ - - /* NTSC/PAL format */ - buf[3] = s->sys->dsf ? 0x80 : 0x00; - - /* 25Mbps or 50Mbps */ - buf[80*5 + 48 + 3] = (s->sys->pix_fmt == PIX_FMT_YUV422P) ? 0x4 : 0x0; + dv_format_frame(s, buf); return s->sys->frame_size; } diff --git a/libavcodec/dvdata.h b/libavcodec/dvdata.h index a3d42d66c1..87d34c0430 100644 --- a/libavcodec/dvdata.h +++ b/libavcodec/dvdata.h @@ -2624,6 +2624,29 @@ static const DVprofile dv_profiles[] = { } }; +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_video_recdate = 0x62, + dv_video_rectime = 0x63, + dv_unknown_pack = 0xff, +}; + /* minimum number of bytes to read from a DV stream in order to determine the profile */ #define DV_PROFILE_BYTES (6*80) /* 6 DIF blocks */ @@ -2663,3 +2686,37 @@ static inline const DVprofile* dv_codec_profile(AVCodecContext* codec) return NULL; } + +static inline int dv_write_dif_id(enum dv_section_type t, uint8_t chan_num, uint8_t seq_num, + uint8_t dif_num, uint8_t* buf) +{ + buf[0] = (uint8_t)t; /* Section type */ + buf[1] = (seq_num<<4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */ + (chan_num << 3) | /* FSC: for 50Mb/s 0 - first channel; 1 - second */ + 7; /* reserved -- always 1 */ + buf[2] = dif_num; /* DIF block number Video: 0-134, Audio: 0-8 */ + return 3; +} + + +static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf) +{ + if (syb_num == 0 || syb_num == 6) { + buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */ + (0<<4) | /* AP3 (Subcode application ID) */ + 0x0f; /* reserved -- always 1 */ + } + else if (syb_num == 11) { + buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */ + 0x7f; /* reserved -- always 1 */ + } + else { + buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */ + (0<<4) | /* APT (Track application ID) */ + 0x0f; /* reserved -- always 1 */ + } + buf[1] = 0xf0 | /* reserved -- always 1 */ + (syb_num & 0x0f); /* SSYB number 0 - 11 */ + buf[2] = 0xff; /* reserved -- always 1 */ + return 3; +} diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 0429701b21..8f0c9bf43e 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -434,6 +434,16 @@ int fifo_read(FifoBuffer *f, uint8_t *buf, int buf_size, uint8_t **rptr_ptr); void fifo_write(FifoBuffer *f, const uint8_t *buf, int size, uint8_t **wptr_ptr); int put_fifo(ByteIOContext *pb, FifoBuffer *f, int buf_size, uint8_t **rptr_ptr); void fifo_realloc(FifoBuffer *f, unsigned int size); +static inline uint8_t fifo_peek(FifoBuffer *f, int offs) +{ + return f->buffer[(f->rptr - f->buffer + offs) % (f->end - f->buffer)]; +} +static inline void fifo_drain(FifoBuffer *f, int size) +{ + f->rptr += size; + if (f->rptr >= f->end) + f->rptr = f->buffer + (f->rptr - f->end); +} /* media file input */ AVInputFormat *av_find_input_format(const char *short_name); diff --git a/libavformat/dv.c b/libavformat/dv.c index b39d0b16b6..1e139ab3d7 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -49,93 +49,11 @@ struct DVMuxContext { FifoBuffer audio_data[2]; /* 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 */ uint8_t frame_buf[DV_MAX_FRAME_SIZE]; /* frame under contruction */ }; -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_video_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 }, @@ -189,20 +107,6 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu 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 */ - (apt & 0x07); /* APT: Track application ID */ - buf[2] = (0 << 7) | /* TF1: audio data is 0 - valid; 1 - invalid */ - (0x0f << 3) | /* reserved -- always 1 */ - (apt & 0x07); /* AP1: Audio application ID */ - buf[3] = (0 << 7) | /* TF2: video data is 0 - valid; 1 - invalid */ - (0x0f << 3) | /* reserved -- always 1 */ - (apt & 0x07); /* AP2: Video application ID */ - buf[4] = (0 << 7) | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */ - (0x0f << 3) | /* reserved -- always 1 */ - (apt & 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)); @@ -293,117 +197,13 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu ((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 */ - (apt << 2); /* 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 chan_num, uint8_t seq_num, - uint8_t dif_num, uint8_t* buf) -{ - buf[0] = (uint8_t)t; /* Section type */ - buf[1] = (seq_num<<4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */ - (chan_num << 3) | /* FSC: for 50Mb/s 0 - first channel; 1 - second */ - 7; /* reserved -- always 1 */ - buf[2] = dif_num; /* DIF block number Video: 0-134, Audio: 0-8 */ - return 3; -} - -static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf) -{ - if (syb_num == 0 || syb_num == 6) { - buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */ - (0<<4) | /* AP3 (Subcode application ID) */ - 0x0f; /* reserved -- always 1 */ - } - else if (syb_num == 11) { - buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */ - 0x7f; /* reserved -- always 1 */ - } - else { - buf[0] = (fr<<7) | /* FR ID 1 - first half of each channel; 0 - second */ - (0<<4) | /* APT (Track application ID) */ - 0x0f; /* reserved -- always 1 */ - } - buf[1] = 0xf0 | /* reserved -- always 1 */ - (syb_num & 0x0f); /* SSYB number 0 - 11 */ - buf[2] = 0xff; /* reserved -- always 1 */ - return 3; -} - -static void dv_format_frame(DVMuxContext *c, uint8_t* buf) -{ - int chan, i, j, k; - - for (chan = 0; chan < c->sys->n_difchan; chan++) { - for (i = 0; i < c->sys->difseg_size; i++) { - memset(buf, 0xff, 80 * 6); /* First 6 DIF blocks are for control data */ - - /* DV header: 1DIF */ - buf += dv_write_dif_id(dv_sect_header, chan, i, 0, buf); - buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf); - buf += 72; /* unused bytes */ - - /* DV subcode: 2DIFs */ - for (j = 0; j < 2; j++) { - buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf); - for (k = 0; k < 6; k++) { - buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf); - buf += dv_write_pack(dv_ssyb_packs_dist[i][k], c, buf); - } - buf += 29; /* unused bytes */ - } - - /* DV VAUX: 3DIFs */ - for (j = 0; j < 3; j++) { - buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf); - for (k = 0; k < 15 ; k++) - buf += dv_write_pack(dv_vaux_packs_dist[i][k], c, buf); - buf += 2; /* unused bytes */ - } - - /* DV Audio/Video: 135 Video DIFs + 9 Audio DIFs */ - for (j = 0; j < 135; j++) { - if (j%15 == 0) { - memset(buf, 0xff, 80); - buf += dv_write_dif_id(dv_sect_audio, chan, i, j/15, buf); - buf += 77; /* audio control & shuffled PCM audio */ - } - buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf); - buf += 77; /* 1 video macro block: 1 bytes control - 4 * 14 bytes Y 8x8 data - 10 bytes Cr 8x8 data - 10 bytes Cb 8x8 data */ - } - } - } -} - -static void dv_inject_audio(DVMuxContext *c, const uint8_t* pcm, int channel, uint8_t* frame_ptr) +static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr) { int i, j, d, of, size; size = 4 * dv_audio_frame_size(c->sys, c->frames); @@ -417,30 +217,40 @@ static void dv_inject_audio(DVMuxContext *c, const uint8_t* pcm, int channel, ui if (of*2 >= size) continue; - frame_ptr[d] = pcm[of*2+1]; // FIXME: may be we have to admit - frame_ptr[d+1] = pcm[of*2]; // that DV is a big endian PCM + frame_ptr[d] = fifo_peek(&c->audio_data[channel], of*2+1); // FIXME: may be we have to admit + frame_ptr[d+1] = fifo_peek(&c->audio_data[channel], of*2); // that DV is a big endian PCM } frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ } } } -static void dv_inject_video(DVMuxContext *c, const uint8_t* video_data, uint8_t* frame_ptr) +static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame) { - int chan, i, j; - int ptr = 0; - - for (chan = 0; chan < c->sys->n_difchan; chan++) { - for (i = 0; i < c->sys->difseg_size; i++) { - ptr += 6 * 80; /* skip DIF segment header */ - for (j = 0; j < 135; j++) { - if (j%15 == 0) - ptr += 80; /* skip Audio DIF */ - ptr += 3; - memcpy(frame_ptr + ptr, video_data + ptr, 77); - ptr += 77; + int j, k; + uint8_t* buf; + + for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80) { + /* DV subcode: 2nd and 3d DIFs */ + for (j = 80; j < 80 * 3; j += 80) { + for (k = 6; k < 6 * 8; k += 8) + dv_write_pack(dv_timecode, c, &buf[j+k]); + + if (((long)(buf-frame)/(c->sys->frame_size/(c->sys->difseg_size*c->sys->n_difchan))%c->sys->difseg_size) > 5) { /* FIXME: is this really needed ? */ + dv_write_pack(dv_video_recdate, c, &buf[j+14]); + dv_write_pack(dv_video_rectime, c, &buf[j+22]); + dv_write_pack(dv_video_recdate, c, &buf[j+38]); + dv_write_pack(dv_video_rectime, c, &buf[j+46]); } } + + /* DV VAUX: 4th, 5th and 6th 3DIFs */ + for (j = 80*3 + 3; j < 80*6; j += 80) { + dv_write_pack(dv_video_recdate, c, &buf[j+5*2]); + dv_write_pack(dv_video_rectime, c, &buf[j+5*3]); + dv_write_pack(dv_video_recdate, c, &buf[j+5*11]); + dv_write_pack(dv_video_rectime, c, &buf[j+5*12]); + } } } @@ -643,60 +453,52 @@ static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame) int dv_assemble_frame(DVMuxContext *c, AVStream* st, const uint8_t* data, int data_size, uint8_t** frame) { - uint8_t pcm[8192]; - int i; + int i, reqasize; *frame = &c->frame_buf[0]; - if (c->has_audio && c->has_video && - (c->has_audio == -1 || c->has_audio == c->n_ast)) { - /* must be a stale frame */ - dv_format_frame(c, *frame); - c->frames++; - if (c->has_audio > 0) - c->has_audio = 0; - c->has_video = 0; - } + reqasize = 4 * dv_audio_frame_size(c->sys, c->frames); + + switch (st->codec->codec_type) { + case CODEC_TYPE_VIDEO: + /* FIXME: we have to have more sensible approach than this one */ + if (c->has_video) + av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames); - if (st->codec->codec_type == CODEC_TYPE_VIDEO) { - /* FIXME: we have to have more sensible approach than this one */ - if (c->has_video) - av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames); + memcpy(*frame, data, c->sys->frame_size); + c->has_video = 1; + break; + case CODEC_TYPE_AUDIO: + for (i = 0; i < c->n_ast && st != c->ast[i]; i++); + + /* FIXME: we have to have more sensible approach than this one */ + if (fifo_size(&c->audio_data[i], c->audio_data[i].rptr) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) + av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); + fifo_write(&c->audio_data[i], data, data_size, &c->audio_data[i].wptr); - dv_inject_video(c, data, *frame); - c->has_video = 1; - data_size = 0; - if (c->has_audio < 0) - goto out; + /* Lets see if we've got enough audio for one DV frame */ + c->has_audio |= ((reqasize <= fifo_size(&c->audio_data[i], c->audio_data[i].rptr)) << i); + + break; + default: + break; } - for (i = 0; i < c->n_ast; i++) { - int reqasize, fsize; - if (st != c->ast[i]) - continue; - reqasize = 4 * dv_audio_frame_size(c->sys, c->frames); - fsize = fifo_size(&c->audio_data[i], c->audio_data[i].rptr); - if (st->codec->codec_type == CODEC_TYPE_AUDIO || - (c->has_video && fsize >= reqasize)) { - if (fsize + data_size >= reqasize && (c->has_audio < c->n_ast)) { - if (fsize >= reqasize) { - fifo_read(&c->audio_data[i], &pcm[0], reqasize, &c->audio_data[i].rptr); - } else { - fifo_read(&c->audio_data[i], &pcm[0], fsize, &c->audio_data[i].rptr); - memcpy(&pcm[fsize], &data[0], reqasize - fsize); - data += reqasize - fsize; - data_size -= reqasize - fsize; - } - dv_inject_audio(c, &pcm[0], i, *frame); - c->has_audio += 1; - } - /* FIXME: we have to have more sensible approach than this one */ - if (fifo_size(&c->audio_data[i], c->audio_data[i].rptr) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) - av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); - fifo_write(&c->audio_data[i], data, data_size, &c->audio_data[i].wptr); + /* Lets see if we have enough data to construct one DV frame */ + if (c->has_video == 1 && c->has_audio + 1 == 1<n_ast) { + dv_inject_metadata(c, *frame); + for (i=0; in_ast; i++) { + dv_inject_audio(c, i, *frame); + fifo_drain(&c->audio_data[i], reqasize); } + + c->has_video = 0; + c->has_audio = 0; + c->frames++; + + return c->sys->frame_size; } -out: - return ((c->has_audio == -1 || c->has_audio == c->n_ast) && c->has_video) ? c->sys->frame_size : 0; + + return 0; } DVMuxContext* dv_init_mux(AVFormatContext* s) @@ -750,12 +552,9 @@ DVMuxContext* dv_init_mux(AVFormatContext* s) /* Ok, everything seems to be in working order */ c->frames = 0; - c->has_audio = c->n_ast ? 0 : -1; + c->has_audio = 0; c->has_video = 0; c->start_time = (time_t)s->timestamp; - c->aspect = 0; /* 4:3 is the default */ - if ((int)(av_q2d(vst->codec->sample_aspect_ratio) * vst->codec->width / vst->codec->height * 10) == 17) /* 16:9 */ - c->aspect = 0x07; for (i=0; in_ast; i++) { if (c->ast[i] && fifo_init(&c->audio_data[i], 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) < 0) { @@ -767,8 +566,6 @@ DVMuxContext* dv_init_mux(AVFormatContext* s) } } - dv_format_frame(c, &c->frame_buf[0]); - return c; bail_out: diff --git a/tests/ffmpeg.regression.ref b/tests/ffmpeg.regression.ref index 5958ae26ba..1aec954d3b 100644 --- a/tests/ffmpeg.regression.ref +++ b/tests/ffmpeg.regression.ref @@ -141,11 +141,11 @@ f998347483cef957af497aa0055dca0c *./data/a-snow53.avi 3534748 ./data/a-snow53.avi 799d3db687f6cdd7a837ec156efc171f *./data/out.yuv stddev: 0.00 PSNR:99.99 bytes:7602176 -85529d9838c5a8aef041445fa8ef3c85 *./data/a-dv.dv +2fcbcdc63816e1321bf4b6b5380338d2 *./data/a-dv.dv 7200000 ./data/a-dv.dv c2082cd8adf417c4ebc32654e446cba1 *./data/out.yuv stddev: 8.86 PSNR:29.17 bytes:7602176 -ff5eb084624f9a2846840a215b95a112 *./data/a-dv.dv +4f71942eb699bf3b12508a9e777a319f *./data/a-dv.dv 14400000 ./data/a-dv.dv fc866b8879a34f5b440647e5135e4bfb *./data/out.yuv stddev: 8.45 PSNR:29.58 bytes:7602176 diff --git a/tests/libav.regression.ref b/tests/libav.regression.ref index 458ae427f4..f337e05ee1 100644 --- a/tests/libav.regression.ref +++ b/tests/libav.regression.ref @@ -28,7 +28,7 @@ ffmpeg regression test 8bf16d40a2ec19fa36b124a928e47e23 *./data/b-libav.nut 332358 ./data/b-libav.nut ./data/b-libav.nut CRC=0x1fdd352c -2cc647904d3cca01703f36056b9d3f42 *./data/b-libav.dv +26c41db318d9aacfd6b9e734c0ea4d94 *./data/b-libav.dv 3600000 ./data/b-libav.dv ./data/b-libav.dv CRC=0xa6b8b635 304ee17506e4526ba04285f6cd14630f *./data/b-libav.gxf diff --git a/tests/rotozoom.regression.ref b/tests/rotozoom.regression.ref index 3af0b93a5d..5652f2d62b 100644 --- a/tests/rotozoom.regression.ref +++ b/tests/rotozoom.regression.ref @@ -141,11 +141,11 @@ stddev: 10.93 PSNR:27.34 bytes:7602176 2726606 ./data/a-snow53.avi dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv stddev: 0.00 PSNR:99.99 bytes:7602176 -6568326ee439099e8a0e1680336ed351 *./data/a-dv.dv +af9f474238c9c68cb32e389659ee25ab *./data/a-dv.dv 7200000 ./data/a-dv.dv bb69dda7a84a5b166434e28e1243d3d1 *./data/out.yuv stddev: 2.99 PSNR:38.59 bytes:7602176 -177cbbbe50cbb67ae3bd6e7f10ff968b *./data/a-dv.dv +91dc1c1dc4a8cca72f27d85db6d7636f *./data/a-dv.dv 14400000 ./data/a-dv.dv 74b01209bb5e096d570dd4df112bb82d *./data/out.yuv stddev: 2.98 PSNR:38.61 bytes:7602176