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

📄 dv.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 3 页
字号:
            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 + -