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

📄 swf.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 2 页
字号:
        if (audio_enc->channels == 2)
            v |= 0x01; /* stereo playback */
        put_byte(&s->pb, v);
        v |= 0x20; /* mp3 compressed */
        put_byte(&s->pb, v);
        put_le16(&s->pb, swf->samples_per_frame);  /* avg samples per frame */
        put_le16(&s->pb, 0);

        put_swf_end_tag(s);
    }

    put_flush_packet(&s->pb);
    return 0;
}

static int swf_write_video(AVFormatContext *s,
                           AVCodecContext *enc, const uint8_t *buf, int size)
{
    SWFContext *swf = s->priv_data;
    ByteIOContext *pb = &s->pb;

    /* Flash Player limit */
    if (swf->swf_frame_number == 16000) {
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
    }

    if (swf->video_type == CODEC_ID_VP6F ||
        swf->video_type == CODEC_ID_FLV1) {
        if (swf->video_frame_number == 0) {
            /* create a new video object */
            put_swf_tag(s, TAG_VIDEOSTREAM);
            put_le16(pb, VIDEO_ID);
            put_le16(pb, 15000); /* hard flash player limit */
            put_le16(pb, enc->width);
            put_le16(pb, enc->height);
            put_byte(pb, 0);
            put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
            put_swf_end_tag(s);

            /* place the video object for the first time */
            put_swf_tag(s, TAG_PLACEOBJECT2);
            put_byte(pb, 0x36);
            put_le16(pb, 1);
            put_le16(pb, VIDEO_ID);
            put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
            put_le16(pb, swf->video_frame_number);
            put_byte(pb, 'v');
            put_byte(pb, 'i');
            put_byte(pb, 'd');
            put_byte(pb, 'e');
            put_byte(pb, 'o');
            put_byte(pb, 0x00);
            put_swf_end_tag(s);
        } else {
            /* mark the character for update */
            put_swf_tag(s, TAG_PLACEOBJECT2);
            put_byte(pb, 0x11);
            put_le16(pb, 1);
            put_le16(pb, swf->video_frame_number);
            put_swf_end_tag(s);
        }

        /* set video frame data */
        put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);
        put_le16(pb, VIDEO_ID);
        put_le16(pb, swf->video_frame_number++);
        put_buffer(pb, buf, size);
        put_swf_end_tag(s);
    } else if (swf->video_type == CODEC_ID_MJPEG) {
        if (swf->swf_frame_number > 0) {
            /* remove the shape */
            put_swf_tag(s, TAG_REMOVEOBJECT);
            put_le16(pb, SHAPE_ID); /* shape ID */
            put_le16(pb, 1); /* depth */
            put_swf_end_tag(s);

            /* free the bitmap */
            put_swf_tag(s, TAG_FREECHARACTER);
            put_le16(pb, BITMAP_ID);
            put_swf_end_tag(s);
        }

        put_swf_tag(s, TAG_JPEG2 | TAG_LONG);

        put_le16(pb, BITMAP_ID); /* ID of the image */

        /* a dummy jpeg header seems to be required */
        put_byte(pb, 0xff);
        put_byte(pb, 0xd8);
        put_byte(pb, 0xff);
        put_byte(pb, 0xd9);
        /* write the jpeg image */
        put_buffer(pb, buf, size);

        put_swf_end_tag(s);

        /* draw the shape */

        put_swf_tag(s, TAG_PLACEOBJECT);
        put_le16(pb, SHAPE_ID); /* shape ID */
        put_le16(pb, 1); /* depth */
        put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);
        put_swf_end_tag(s);
    } else {
        /* invalid codec */
    }

    swf->swf_frame_number ++;

    /* streaming sound always should be placed just before showframe tags */
    if (swf->audio_type && swf->audio_in_pos) {
        put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
        put_le16(pb, swf->sound_samples);
        put_le16(pb, 0); // seek samples
        put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
        put_swf_end_tag(s);

        /* update FIFO */
        swf->sound_samples = 0;
        swf->audio_in_pos = 0;
    }

    /* output the frame */
    put_swf_tag(s, TAG_SHOWFRAME);
    put_swf_end_tag(s);

    put_flush_packet(&s->pb);

    return 0;
}

static int swf_write_audio(AVFormatContext *s,
                           AVCodecContext *enc, const uint8_t *buf, int size)
{
    SWFContext *swf = s->priv_data;

    /* Flash Player limit */
    if (swf->swf_frame_number == 16000) {
        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
    }

    if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
        av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
        return -1;
    }

    memcpy(swf->audio_fifo +  swf->audio_in_pos, buf, size);
    swf->audio_in_pos += size;
    swf->sound_samples += enc->frame_size;

    /* if audio only stream make sure we add swf frames */
    if (swf->video_type == 0) {
        swf_write_video(s, enc, 0, 0);
    }

    return 0;
}

static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
{
    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
    if (codec->codec_type == CODEC_TYPE_AUDIO)
        return swf_write_audio(s, codec, pkt->data, pkt->size);
    else
        return swf_write_video(s, codec, pkt->data, pkt->size);
}

static int swf_write_trailer(AVFormatContext *s)
{
    SWFContext *swf = s->priv_data;
    ByteIOContext *pb = &s->pb;
    AVCodecContext *enc, *video_enc;
    int file_size, i;

    video_enc = NULL;
    for(i=0;i<s->nb_streams;i++) {
        enc = s->streams[i]->codec;
        if (enc->codec_type == CODEC_TYPE_VIDEO)
            video_enc = enc;
    }

    put_swf_tag(s, TAG_END);
    put_swf_end_tag(s);

    put_flush_packet(&s->pb);

    /* patch file size and number of frames if not streamed */
    if (!url_is_streamed(&s->pb) && video_enc) {
        file_size = url_ftell(pb);
        url_fseek(pb, 4, SEEK_SET);
        put_le32(pb, file_size);
        url_fseek(pb, swf->duration_pos, SEEK_SET);
        put_le16(pb, video_enc->frame_number);
        url_fseek(pb, file_size, SEEK_SET);
    }
    return 0;
}
#endif //CONFIG_MUXERS

/*********************************************/
/* Extract FLV encoded frame and MP3 from swf
   Note that the detection of the real frame
   is inaccurate at this point as it can be
   quite tricky to determine, you almost certainly
   will get a bad audio/video sync */

static int get_swf_tag(ByteIOContext *pb, int *len_ptr)
{
    int tag, len;

    if (url_feof(pb))
        return -1;

    tag = get_le16(pb);
    len = tag & 0x3f;
    tag = tag >> 6;
    if (len == 0x3f) {
        len = get_le32(pb);
    }
//    av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len);
    *len_ptr = len;
    return tag;
}


static int swf_probe(AVProbeData *p)
{
    /* check file header */
    if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&
        p->buf[2] == 'S')
        return AVPROBE_SCORE_MAX;
    else
        return 0;
}

static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
    SWFContext *swf = s->priv_data;
    ByteIOContext *pb = &s->pb;
    int nbits, len, tag;

    tag = get_be32(pb) & 0xffffff00;

    if (tag == MKBETAG('C', 'W', 'S', 0)) {
        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
        return AVERROR(EIO);
    }
    if (tag != MKBETAG('F', 'W', 'S', 0))
        return AVERROR(EIO);
    get_le32(pb);
    /* skip rectangle size */
    nbits = get_byte(pb) >> 3;
    len = (4 * nbits - 3 + 7) / 8;
    url_fskip(pb, len);
    swf->frame_rate = get_le16(pb); /* 8.8 fixed */
    get_le16(pb); /* frame count */

    swf->samples_per_frame = 0;
    s->ctx_flags |= AVFMTCTX_NOHEADER;
    return 0;
}

static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    SWFContext *swf = s->priv_data;
    ByteIOContext *pb = &s->pb;
    AVStream *vst = NULL, *ast = NULL, *st = 0;
    int tag, len, i, frame, v;

    for(;;) {
        tag = get_swf_tag(pb, &len);
        if (tag < 0)
            return AVERROR(EIO);
        if (tag == TAG_VIDEOSTREAM && !vst) {
            int ch_id = get_le16(pb);
            get_le16(pb);
            get_le16(pb);
            get_le16(pb);
            get_byte(pb);
            /* Check for FLV1 */
            vst = av_new_stream(s, ch_id);
            vst->codec->codec_type = CODEC_TYPE_VIDEO;
            vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
            av_set_pts_info(vst, 64, 256, swf->frame_rate);
            vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
            len -= 10;
        } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) {
            /* streaming found */
            int sample_rate_code;
            get_byte(pb);
            v = get_byte(pb);
            swf->samples_per_frame = get_le16(pb);
            ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */
            swf->audio_stream_index = ast->index;
            ast->codec->channels = 1 + (v&1);
            ast->codec->codec_type = CODEC_TYPE_AUDIO;
            ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
            ast->need_parsing = AVSTREAM_PARSE_FULL;
            sample_rate_code= (v>>2) & 3;
            if (!sample_rate_code)
                return AVERROR(EIO);
            ast->codec->sample_rate = 11025 << (sample_rate_code-1);
            av_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
            len -= 4;
        } else if (tag == TAG_VIDEOFRAME) {
            int ch_id = get_le16(pb);
            len -= 2;
            for(i=0; i<s->nb_streams; i++) {
                st = s->streams[i];
                if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) {
                    frame = get_le16(pb);
                    av_get_packet(pb, pkt, len-2);
                    pkt->pts = frame;
                    pkt->stream_index = st->index;
                    return pkt->size;
                }
            }
        } else if (tag == TAG_STREAMBLOCK) {
            st = s->streams[swf->audio_stream_index];
            if (st->codec->codec_id == CODEC_ID_MP3) {
                url_fskip(pb, 4);
                av_get_packet(pb, pkt, len-4);
            } else { // ADPCM, PCM
                av_get_packet(pb, pkt, len);
            }
            pkt->stream_index = st->index;
            return pkt->size;
        } else if (tag == TAG_JPEG2) {
            for (i=0; i<s->nb_streams; i++) {
                st = s->streams[i];
                if (st->id == -2)
                    break;
            }
            if (i == s->nb_streams) {
                vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */
                vst->codec->codec_type = CODEC_TYPE_VIDEO;
                vst->codec->codec_id = CODEC_ID_MJPEG;
                av_set_pts_info(vst, 64, 256, swf->frame_rate);
                vst->codec->time_base = (AVRational){ 256, swf->frame_rate };
                st = vst;
            }
            get_le16(pb); /* BITMAP_ID */
            av_new_packet(pkt, len-2);
            get_buffer(pb, pkt->data, 4);
            if (AV_RB32(pkt->data) == 0xffd8ffd9 ||
                AV_RB32(pkt->data) == 0xffd9ffd8) {
                /* old SWF files containing SOI/EOI as data start */
                /* files created by swink have reversed tag */
                pkt->size -= 4;
                get_buffer(pb, pkt->data, pkt->size);
            } else {
                get_buffer(pb, pkt->data + 4, pkt->size - 4);
            }
            pkt->stream_index = st->index;
            return pkt->size;
        }
        url_fskip(pb, len);
    }
    return 0;
}

static int swf_read_close(AVFormatContext *s)
{
    return 0;
}

#ifdef CONFIG_SWF_DEMUXER
AVInputFormat swf_demuxer = {
    "swf",
    "Flash format",
    sizeof(SWFContext),
    swf_probe,
    swf_read_header,
    swf_read_packet,
    swf_read_close,
};
#endif
#ifdef CONFIG_SWF_MUXER
AVOutputFormat swf_muxer = {
    "swf",
    "Flash format",
    "application/x-shockwave-flash",
    "swf",
    sizeof(SWFContext),
    CODEC_ID_MP3,
    CODEC_ID_FLV1,
    swf_write_header,
    swf_write_packet,
    swf_write_trailer,
};
#endif

⌨️ 快捷键说明

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