📄 dv.c
字号:
fprintf(stderr, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames); dv_inject_video(c, data, *frame); c->has_video = 1; data_size = 0; } reqasize = 4 * dv_audio_frame_size(c->sys, c->frames); fsize = fifo_size(&c->audio_data, c->audio_data.rptr); if (st->codec.codec_type == CODEC_TYPE_AUDIO || (c->has_video && fsize >= reqasize)) { if (fsize + data_size >= reqasize && !c->has_audio) { if (fsize >= reqasize) { fifo_read(&c->audio_data, &pcm[0], reqasize, &c->audio_data.rptr); } else { fifo_read(&c->audio_data, &pcm[0], fsize, &c->audio_data.rptr); memcpy(&pcm[fsize], &data[0], reqasize - fsize); data += reqasize - fsize; data_size -= reqasize - fsize; } dv_inject_audio(c, &pcm[0], *frame); c->has_audio = 1; } /* FIXME: we have to have more sensible approach than this one */ if (fifo_size(&c->audio_data, c->audio_data.rptr) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) fprintf(stderr, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); fifo_write(&c->audio_data, (uint8_t *)data, data_size, &c->audio_data.wptr); } return (c->has_audio && c->has_video) ? c->sys->frame_size : 0;}DVMuxContext* dv_init_mux(AVFormatContext* s){ DVMuxContext *c; AVStream *vst; AVStream *ast; c = av_mallocz(sizeof(DVMuxContext)); if (!c) return NULL; if (s->nb_streams != 2) goto bail_out; /* We have to sort out where audio and where video stream is */ if (s->streams[0]->codec.codec_type == CODEC_TYPE_VIDEO && s->streams[1]->codec.codec_type == CODEC_TYPE_AUDIO) { vst = s->streams[0]; ast = s->streams[1]; } else if (s->streams[1]->codec.codec_type == CODEC_TYPE_VIDEO && s->streams[0]->codec.codec_type == CODEC_TYPE_AUDIO) { vst = s->streams[1]; ast = s->streams[0]; } else goto bail_out; /* Some checks -- DV format is very picky about its incoming streams */ if (vst->codec.codec_id != CODEC_ID_DVVIDEO || ast->codec.codec_id != CODEC_ID_PCM_S16LE) goto bail_out; if (ast->codec.sample_rate != 48000 || ast->codec.channels != 2) goto bail_out; c->sys = dv_codec_profile(&vst->codec); if (!c->sys) goto bail_out; /* Ok, everything seems to be in working order */ c->frames = 0; c->has_audio = c->has_video = 0; c->start_time = time(NULL); 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; if (fifo_init(&c->audio_data, 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) < 0) goto bail_out; dv_format_frame(c, &c->frame_buf[0]); return c; bail_out: av_free(c); return NULL;}void dv_delete_mux(DVMuxContext *c){ fifo_free(&c->audio_data);}DVDemuxContext* dv_init_demux(AVFormatContext *s){ DVDemuxContext *c; c = av_mallocz(sizeof(DVDemuxContext)); if (!c) return NULL; c->vst = av_new_stream(s, 0); c->ast[0] = av_new_stream(s, 0); if (!c->vst || !c->ast[0]) goto fail; c->fctx = s; c->ast[1] = NULL; c->ach = 0; c->audio_pkt[0].size = 0; c->audio_pkt[1].size = 0; c->vst->codec.codec_type = CODEC_TYPE_VIDEO; c->vst->codec.codec_id = CODEC_ID_DVVIDEO; c->vst->codec.bit_rate = 25000000; c->ast[0]->codec.codec_type = CODEC_TYPE_AUDIO; c->ast[0]->codec.codec_id = CODEC_ID_PCM_S16LE; s->ctx_flags |= AVFMTCTX_NOHEADER; return c; fail: if (c->vst) av_free(c->vst); if (c->ast[0]) av_free(c->ast[0]); av_free(c); return NULL;}static void __destruct_pkt(struct AVPacket *pkt){ pkt->data = NULL; pkt->size = 0; return;}int dv_get_packet(DVDemuxContext *c, AVPacket *pkt){ int size = -1; int i; for (i=0; i<c->ach; i++) { if (c->ast[i] && c->audio_pkt[i].size) { *pkt = c->audio_pkt[i]; c->audio_pkt[i].size = 0; size = pkt->size; break; } } return size;}int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, uint8_t* buf, int buf_size){ int size, i; if (buf_size < 4 || buf_size < dv_frame_profile(buf)->frame_size) return -1; /* Broken frame, or not enough data */ /* Queueing audio packet */ /* FIXME: in case of no audio/bad audio we have to do something */ size = dv_extract_audio_info(c, buf); c->audio_pkt[0].data = c->audio_pkt[1].data = NULL; for (i=0; i<c->ach; i++) { if (av_new_packet(&c->audio_pkt[i], size) < 0) return AVERROR_NOMEM; c->audio_pkt[i].stream_index = c->ast[i]->index; } dv_extract_audio(buf, c->audio_pkt[0].data, c->audio_pkt[1].data); /* Now it's time to return video packet */ size = dv_extract_video_info(c, buf); av_init_packet(pkt); pkt->destruct = __destruct_pkt; pkt->data = buf; pkt->size = size; pkt->flags |= PKT_FLAG_KEY; pkt->stream_index = c->vst->id; return size;} /************************************************************ * Implementation of the easiest DV storage of all -- raw DV. ************************************************************/ typedef struct RawDVContext { uint8_t buf[144000]; DVDemuxContext* dv_demux;} RawDVContext;static int dv_read_header(AVFormatContext *s, AVFormatParameters *ap){ RawDVContext *c = s->priv_data; c->dv_demux = dv_init_demux(s); return c->dv_demux ? 0 : -1;}static int dv_read_packet(AVFormatContext *s, AVPacket *pkt){ int size; RawDVContext *c = s->priv_data; size = dv_get_packet(c->dv_demux, pkt); if (size < 0) { if (get_buffer(&s->pb, c->buf, 4) <= 0) return -EIO; size = dv_frame_profile(c->buf)->frame_size; if (get_buffer(&s->pb, c->buf + 4, size - 4) <= 0) return -EIO; size = dv_produce_packet(c->dv_demux, pkt, c->buf, size); } return size;}static int dv_read_close(AVFormatContext *s){ RawDVContext *c = s->priv_data; av_free(c->dv_demux); return 0;}static int dv_write_header(AVFormatContext *s){ s->priv_data = dv_init_mux(s); if (!s->priv_data) { fprintf(stderr, "Can't initialize DV format!\n" "Make sure that you supply exactly two streams:\n" " video: 25fps or 29.97fps, audio: 2ch/48Khz/PCM\n"); return -1; } return 0;}static int dv_write_packet(struct AVFormatContext *s, int stream_index, const uint8_t *buf, int size, int64_t pts){ uint8_t* frame; int fsize; fsize = dv_assemble_frame((DVMuxContext *)s->priv_data, s->streams[stream_index], buf, size, &frame); if (fsize > 0) { put_buffer(&s->pb, frame, fsize); put_flush_packet(&s->pb); } return fsize;}/* * We might end up with some extra A/V data without matching counterpart. * E.g. video data without enough audio to write the complete frame. * Currently we simply drop the last frame. I don't know whether this * is the best strategy of all */static int dv_write_trailer(struct AVFormatContext *s){ dv_delete_mux((DVMuxContext *)s->priv_data); return 0;}static AVInputFormat dv_iformat = { "dv", "DV video format", sizeof(RawDVContext), NULL, dv_read_header, dv_read_packet, dv_read_close, .extensions = "dv",};static AVOutputFormat dv_oformat = { "dv", "DV video format", NULL, "dv", sizeof(DVMuxContext), CODEC_ID_PCM_S16LE, CODEC_ID_DVVIDEO, dv_write_header, dv_write_packet, dv_write_trailer,};int dv_init(void){ av_register_input_format(&dv_iformat); av_register_output_format(&dv_oformat); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -