📄 dv.c
字号:
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], (uint8_t *)data, data_size, &c->audio_data[i].wptr); } }out: return ((c->has_audio == -1 || c->has_audio == c->n_ast) && c->has_video) ? c->sys->frame_size : 0;}DVMuxContext* dv_init_mux(AVFormatContext* s){ DVMuxContext *c; AVStream *vst = NULL; int i; /* we support at most 1 video and 2 audio streams */ if (s->nb_streams > 3) return NULL; c = av_mallocz(sizeof(DVMuxContext)); if (!c) return NULL; c->n_ast = 0; c->ast[0] = c->ast[1] = NULL; /* We have to sort out where audio and where video stream is */ for (i=0; i<s->nb_streams; i++) { switch (s->streams[i]->codec->codec_type) { case CODEC_TYPE_VIDEO: vst = s->streams[i]; break; case CODEC_TYPE_AUDIO: c->ast[c->n_ast++] = s->streams[i]; break; default: goto bail_out; } } /* Some checks -- DV format is very picky about its incoming streams */ if (!vst || vst->codec->codec_id != CODEC_ID_DVVIDEO) goto bail_out; for (i=0; i<c->n_ast; i++) { if (c->ast[i] && (c->ast[i]->codec->codec_id != CODEC_ID_PCM_S16LE || c->ast[i]->codec->sample_rate != 48000 || c->ast[i]->codec->channels != 2)) goto bail_out; } c->sys = dv_codec_profile(vst->codec); if (!c->sys) goto bail_out; if((c->n_ast > 1) && (c->sys->n_difchan < 2)) { /* only 1 stereo pair is allowed in 25Mbps mode */ goto bail_out; } /* Ok, everything seems to be in working order */ c->frames = 0; c->has_audio = c->n_ast ? 0 : -1; 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; i<c->n_ast; i++) { if (c->ast[i] && fifo_init(&c->audio_data[i], 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) < 0) { while (i>0) { i--; fifo_free(&c->audio_data[i]); } 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){ int i; for (i=0; i < c->n_ast; i++) fifo_free(&c->audio_data[i]);}DVDemuxContext* dv_init_demux(AVFormatContext *s){ DVDemuxContext *c; c = av_mallocz(sizeof(DVDemuxContext)); if (!c) return NULL; c->vst = av_new_stream(s, 0); if (!c->vst) { av_free(c); return NULL; } c->sys = NULL; c->fctx = s; c->ast[0] = c->ast[1] = NULL; c->ach = 0; c->frames = 0; c->abytes = 0; c->vst->codec->codec_type = CODEC_TYPE_VIDEO; c->vst->codec->codec_id = CODEC_ID_DVVIDEO; c->vst->codec->bit_rate = 25000000; c->vst->start_time = 0; return c;}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 < DV_PROFILE_BYTES || !(c->sys = dv_frame_profile(buf)) || buf_size < c->sys->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); for (i=0; i<c->ach; i++) { c->audio_pkt[i].size = size; c->audio_pkt[i].pts = c->abytes * 30000*8 / c->ast[i]->codec->bit_rate; } dv_extract_audio(buf, c->audio_buf[0], c->audio_buf[1], c->sys); c->abytes += size; /* Now it's time to return video packet */ size = dv_extract_video_info(c, buf); av_init_packet(pkt); pkt->data = buf; pkt->size = size; pkt->flags |= PKT_FLAG_KEY; pkt->stream_index = c->vst->id; pkt->pts = c->frames; c->frames++; return size;}static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c, int64_t timestamp, int flags){ // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk) const DVprofile* sys = dv_codec_profile(c->vst->codec); int64_t offset; int64_t size = url_fsize(&s->pb); int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size; offset = sys->frame_size * timestamp; if (offset > max_offset) offset = max_offset; else if (offset < 0) offset = 0; return offset;}void dv_flush_audio_packets(DVDemuxContext *c){ c->audio_pkt[0].size = c->audio_pkt[1].size = 0;}/************************************************************ * Implementation of the easiest DV storage of all -- raw DV. ************************************************************/typedef struct RawDVContext { DVDemuxContext* dv_demux; uint8_t buf[DV_MAX_FRAME_SIZE];} RawDVContext;static int dv_read_header(AVFormatContext *s, AVFormatParameters *ap){ RawDVContext *c = s->priv_data; c->dv_demux = dv_init_demux(s); if (!c->dv_demux) return -1; if (get_buffer(&s->pb, c->buf, DV_PROFILE_BYTES) <= 0 || url_fseek(&s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0) return AVERROR_IO; c->dv_demux->sys = dv_frame_profile(c->buf); s->bit_rate = av_rescale(c->dv_demux->sys->frame_size * 8, c->dv_demux->sys->frame_rate, c->dv_demux->sys->frame_rate_base); return 0;}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) { size = c->dv_demux->sys->frame_size; if (get_buffer(&s->pb, c->buf, size) <= 0) return AVERROR_IO; size = dv_produce_packet(c->dv_demux, pkt, c->buf, size); } return size;}static int dv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags){ RawDVContext *r = s->priv_data; DVDemuxContext *c = r->dv_demux; int64_t offset= dv_frame_offset(s, c, timestamp, flags); c->frames= offset / c->sys->frame_size; if (c->ach) c->abytes= av_rescale(c->frames, c->ast[0]->codec->bit_rate * (int64_t)c->sys->frame_rate_base, 8*c->sys->frame_rate); dv_flush_audio_packets(c); return url_fseek(&s->pb, offset, SEEK_SET);}static int dv_read_close(AVFormatContext *s){ RawDVContext *c = s->priv_data; av_free(c->dv_demux); return 0;}#ifdef CONFIG_MUXERSstatic int dv_write_header(AVFormatContext *s){ s->priv_data = dv_init_mux(s); if (!s->priv_data) { av_log(s, AV_LOG_ERROR, "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" " (50Mbps allows an optional second audio stream)\n"); return -1; } return 0;}static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt){ uint8_t* frame; int fsize; fsize = dv_assemble_frame((DVMuxContext *)s->priv_data, s->streams[pkt->stream_index], pkt->data, pkt->size, &frame); if (fsize > 0) { put_buffer(&s->pb, frame, fsize); put_flush_packet(&s->pb); } return 0;}/* * 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;}#endif /* CONFIG_MUXERS */static AVInputFormat dv_iformat = { "dv", "DV video format", sizeof(RawDVContext), NULL, dv_read_header, dv_read_packet, dv_read_close, dv_read_seek, .extensions = "dv,dif",};#ifdef CONFIG_MUXERSstatic 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,};#endifint ff_dv_init(void){ av_register_input_format(&dv_iformat);#ifdef CONFIG_MUXERS av_register_output_format(&dv_oformat);#endif return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -