コード例 #1
0
static int close_slave(TeeSlave *tee_slave)
{
    AVFormatContext *avf;
    unsigned i;
    int ret = 0;

    avf = tee_slave->avf;
    if (!avf)
        return 0;

    if (tee_slave->header_written)
        ret = av_write_trailer(avf);

    if (tee_slave->bsfs) {
        for (i = 0; i < avf->nb_streams; ++i)
            av_bsf_free(&tee_slave->bsfs[i]);
    }
    av_freep(&tee_slave->stream_map);
    av_freep(&tee_slave->bsfs);

    ff_format_io_close(avf, &avf->pb);
    avformat_free_context(avf);
    tee_slave->avf = NULL;
    return ret;
}
コード例 #2
0
ファイル: segment.c プロジェクト: ThomasLee969/libav
static int seg_write_trailer(struct AVFormatContext *s)
{
    SegmentContext *seg = s->priv_data;
    AVFormatContext *oc = seg->avf;
    int ret = 0;

    if (!oc)
        goto fail;

    if (!seg->write_header_trailer) {
        if ((ret = segment_end(oc, 0)) < 0)
            goto fail;
        if ((ret = open_null_ctx(&oc->pb)) < 0)
            goto fail;
        ret = av_write_trailer(oc);
        close_null_ctx(oc->pb);
    } else {
        ret = segment_end(oc, 1);
    }

    if (ret < 0)
        goto fail;

    if (seg->list && seg->list_type == LIST_HLS) {
        if ((ret = segment_hls_window(s, 1) < 0))
            goto fail;
    }

fail:
    ff_format_io_close(s, &seg->pb);
    avformat_free_context(oc);
    return ret;
}
コード例 #3
0
ファイル: tee.c プロジェクト: 15806905685/FFmpeg
static int close_slave(TeeSlave *tee_slave)
{
    AVFormatContext *avf;
    unsigned i;
    int ret = 0;

    avf = tee_slave->avf;
    if (!avf)
        return 0;

    if (tee_slave->header_written)
        ret = av_write_trailer(avf);

    if (tee_slave->bsfs) {
        for (i = 0; i < avf->nb_streams; ++i) {
            AVBitStreamFilterContext *bsf_next, *bsf = tee_slave->bsfs[i];
            while (bsf) {
                bsf_next = bsf->next;
                av_bitstream_filter_close(bsf);
                bsf = bsf_next;
            }
        }
    }
    av_freep(&tee_slave->stream_map);
    av_freep(&tee_slave->bsfs);

    ff_format_io_close(avf, &avf->pb);
    avformat_free_context(avf);
    tee_slave->avf = NULL;
    return ret;
}
コード例 #4
0
ファイル: segment.c プロジェクト: ThomasLee969/libav
static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
{
    SegmentContext *seg = s->priv_data;
    AVFormatContext *oc = seg->avf;
    AVStream *st = s->streams[pkt->stream_index];
    int64_t end_pts = seg->recording_time * seg->number;
    int ret, can_split = 1;

    if (!oc)
        return AVERROR(EINVAL);

    if (seg->has_video) {
        can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
                    pkt->flags & AV_PKT_FLAG_KEY;
    }

    if (can_split && av_compare_ts(pkt->pts, st->time_base, end_pts,
                                   AV_TIME_BASE_Q) >= 0) {
        av_log(s, AV_LOG_DEBUG, "Next segment starts at %d %"PRId64"\n",
               pkt->stream_index, pkt->pts);

        ret = segment_end(oc, seg->individual_header_trailer);

        if (!ret)
            ret = segment_start(s, seg->individual_header_trailer);

        if (ret)
            goto fail;

        oc = seg->avf;

        if (seg->list) {
            if (seg->list_type == LIST_HLS) {
                if ((ret = segment_hls_window(s, 0)) < 0)
                    goto fail;
            } else {
                avio_printf(seg->pb, "%s\n", oc->filename);
                avio_flush(seg->pb);
                if (seg->size && !(seg->number % seg->size)) {
                    ff_format_io_close(s, &seg->pb);
                    if ((ret = s->io_open(s, &seg->pb, seg->list,
                                          AVIO_FLAG_WRITE, NULL)) < 0)
                        goto fail;
                }
            }
        }
    }

    ret = ff_write_chained(oc, pkt->stream_index, pkt, s);

fail:
    if (ret < 0)
        seg_free_context(seg);

    return ret;
}
コード例 #5
0
ファイル: segment.c プロジェクト: ThomasLee969/libav
static int segment_end(AVFormatContext *oc, int write_trailer)
{
    int ret = 0;

    av_write_frame(oc, NULL); /* Flush any buffered data (fragmented mp4) */
    if (write_trailer)
        av_write_trailer(oc);
    ff_format_io_close(oc, &oc->pb);

    return ret;
}
コード例 #6
0
ファイル: segment.c プロジェクト: ThomasLee969/libav
static int segment_hls_window(AVFormatContext *s, int last)
{
    SegmentContext *seg = s->priv_data;
    int i, ret = 0;
    char buf[1024];

    if ((ret = s->io_open(s, &seg->pb, seg->list, AVIO_FLAG_WRITE, NULL)) < 0)
        goto fail;

    avio_printf(seg->pb, "#EXTM3U\n");
    avio_printf(seg->pb, "#EXT-X-VERSION:3\n");
    avio_printf(seg->pb, "#EXT-X-TARGETDURATION:%d\n", (int)seg->time);
    avio_printf(seg->pb, "#EXT-X-MEDIA-SEQUENCE:%d\n",
                FFMAX(0, seg->number - seg->size));

    av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%d\n",
           FFMAX(0, seg->number - seg->size));

    for (i = FFMAX(0, seg->number - seg->size);
         i < seg->number; i++) {
        avio_printf(seg->pb, "#EXTINF:%d,\n", (int)seg->time);
        if (seg->entry_prefix) {
            avio_printf(seg->pb, "%s", seg->entry_prefix);
        }
        ret = av_get_frame_filename(buf, sizeof(buf), s->filename, i);
        if (ret < 0) {
            ret = AVERROR(EINVAL);
            goto fail;
        }
        avio_printf(seg->pb, "%s\n", buf);
    }

    if (last)
        avio_printf(seg->pb, "#EXT-X-ENDLIST\n");
fail:
    ff_format_io_close(s, &seg->pb);

    return ret;
}
コード例 #7
0
ファイル: img2dec.c プロジェクト: Innovattic/FFmpeg
int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
    VideoDemuxData *s = s1->priv_data;
    char filename_bytes[1024];
    char *filename = filename_bytes;
    int i, res;
    int size[3]           = { 0 }, ret[3] = { 0 };
    AVIOContext *f[3]     = { NULL };
    AVCodecParameters *par = s1->streams[0]->codecpar;

    if (!s->is_pipe) {
        /* loop over input */
        if (s->loop && s->img_number > s->img_last) {
            s->img_number = s->img_first;
        }
        if (s->img_number > s->img_last)
            return AVERROR_EOF;
        if (s->pattern_type == PT_NONE) {
            av_strlcpy(filename_bytes, s->path, sizeof(filename_bytes));
        } else if (s->use_glob) {
#if HAVE_GLOB
            filename = s->globstate.gl_pathv[s->img_number];
#endif
        } else {
        if (av_get_frame_filename(filename_bytes, sizeof(filename_bytes),
                                  s->path,
                                  s->img_number) < 0 && s->img_number > 1)
            return AVERROR(EIO);
        }
        for (i = 0; i < 3; i++) {
            if (s1->pb &&
                !strcmp(filename_bytes, s->path) &&
                !s->loop &&
                !s->split_planes) {
                f[i] = s1->pb;
            } else if (s1->io_open(s1, &f[i], filename, AVIO_FLAG_READ, NULL) < 0) {
                if (i >= 1)
                    break;
                av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",
                       filename);
                return AVERROR(EIO);
            }
            size[i] = avio_size(f[i]);

            if (!s->split_planes)
                break;
            filename[strlen(filename) - 1] = 'U' + i;
        }

        if (par->codec_id == AV_CODEC_ID_NONE) {
            AVProbeData pd = { 0 };
            AVInputFormat *ifmt;
            uint8_t header[PROBE_BUF_MIN + AVPROBE_PADDING_SIZE];
            int ret;
            int score = 0;

            ret = avio_read(f[0], header, PROBE_BUF_MIN);
            if (ret < 0)
                return ret;
            memset(header + ret, 0, sizeof(header) - ret);
            avio_skip(f[0], -ret);
            pd.buf = header;
            pd.buf_size = ret;
            pd.filename = filename;

            ifmt = av_probe_input_format3(&pd, 1, &score);
            if (ifmt && ifmt->read_packet == ff_img_read_packet && ifmt->raw_codec_id)
                par->codec_id = ifmt->raw_codec_id;
        }

        if (par->codec_id == AV_CODEC_ID_RAWVIDEO && !par->width)
            infer_size(&par->width, &par->height, size[0]);
    } else {
        f[0] = s1->pb;
        if (avio_feof(f[0]) && s->loop && s->is_pipe)
            avio_seek(f[0], 0, SEEK_SET);
        if (avio_feof(f[0]))
            return AVERROR_EOF;
        if (s->frame_size > 0) {
            size[0] = s->frame_size;
        } else if (!s1->streams[0]->parser) {
            size[0] = avio_size(s1->pb);
        } else {
            size[0] = 4096;
        }
    }

    res = av_new_packet(pkt, size[0] + size[1] + size[2]);
    if (res < 0) {
        goto fail;
    }
    pkt->stream_index = 0;
    pkt->flags       |= AV_PKT_FLAG_KEY;
    if (s->ts_from_file) {
        struct stat img_stat;
        if (stat(filename, &img_stat)) {
            res = AVERROR(EIO);
            goto fail;
        }
        pkt->pts = (int64_t)img_stat.st_mtime;
#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
        if (s->ts_from_file == 2)
            pkt->pts = 1000000000*pkt->pts + img_stat.st_mtim.tv_nsec;
#endif
        av_add_index_entry(s1->streams[0], s->img_number, pkt->pts, 0, 0, AVINDEX_KEYFRAME);
    } else if (!s->is_pipe) {
        pkt->pts      = s->pts;
    }

    if (s->is_pipe)
        pkt->pos = avio_tell(f[0]);

    pkt->size = 0;
    for (i = 0; i < 3; i++) {
        if (f[i]) {
            ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]);
            if (s->loop && s->is_pipe && ret[i] == AVERROR_EOF) {
                if (avio_seek(f[i], 0, SEEK_SET) >= 0) {
                    pkt->pos = 0;
                    ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]);
                }
            }
            if (!s->is_pipe && f[i] != s1->pb)
                ff_format_io_close(s1, &f[i]);
            if (ret[i] > 0)
                pkt->size += ret[i];
        }
    }

    if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) {
        av_packet_unref(pkt);
        if (ret[0] < 0) {
            res = ret[0];
        } else if (ret[1] < 0) {
            res = ret[1];
        } else if (ret[2] < 0) {
            res = ret[2];
        } else {
            res = AVERROR_EOF;
        }
        goto fail;
    } else {
        s->img_count++;
        s->img_number++;
        s->pts++;
        return 0;
    }

fail:
    if (!s->is_pipe) {
        for (i = 0; i < 3; i++) {
            if (f[i] != s1->pb)
                ff_format_io_close(s1, &f[i]);
        }
    }
    return res;
}
コード例 #8
0
ファイル: img2dec.c プロジェクト: ThomasLee969/libav
static int img_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
    VideoDemuxData *s = s1->priv_data;
    char filename[1024];
    int i, res;
    int size[3]           = { 0 }, ret[3] = { 0 };
    AVIOContext *f[3]     = { NULL };
    AVCodecContext *codec = s1->streams[0]->codec;

    if (!s->is_pipe) {
        /* loop over input */
        if (s->loop && s->img_number > s->img_last) {
            s->img_number = s->img_first;
        }
        if (s->img_number > s->img_last)
            return AVERROR_EOF;
        if (av_get_frame_filename(filename, sizeof(filename),
                                  s->path,
                                  s->img_number) < 0 && s->img_number > 1)
            return AVERROR(EIO);
        for (i = 0; i < 3; i++) {
            if (s1->io_open(s1, &f[i], filename, AVIO_FLAG_READ, NULL) < 0) {
                if (i >= 1)
                    break;
                av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",
                       filename);
                return AVERROR(EIO);
            }
            size[i] = avio_size(f[i]);

            if (codec->codec_id != AV_CODEC_ID_RAWVIDEO)
                break;
            filename[strlen(filename) - 1] = 'U' + i;
        }

        if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width)
            infer_size(&codec->width, &codec->height, size[0]);
    } else {
        f[0] = s1->pb;
        if (f[0]->eof_reached)
            return AVERROR(EIO);
        size[0] = 4096;
    }

    res = av_new_packet(pkt, size[0] + size[1] + size[2]);
    if (res < 0)
        return res;
    pkt->stream_index = 0;
    pkt->flags       |= AV_PKT_FLAG_KEY;

    pkt->size = 0;
    for (i = 0; i < 3; i++) {
        if (f[i]) {
            ret[i] = avio_read(f[i], pkt->data + pkt->size, size[i]);
            if (!s->is_pipe)
                ff_format_io_close(s1, &f[i]);
            if (ret[i] > 0)
                pkt->size += ret[i];
        }
    }

    if (ret[0] <= 0 || ret[1] < 0 || ret[2] < 0) {
        av_packet_unref(pkt);
        return AVERROR(EIO); /* signal EOF */
    } else {
        s->img_count++;
        s->img_number++;
        return 0;
    }
}
コード例 #9
0
ファイル: img2enc.c プロジェクト: kevleyski/FFmpeg
static int write_packet(AVFormatContext *s, AVPacket *pkt)
{
    VideoMuxData *img = s->priv_data;
    AVIOContext *pb[4];
    char filename[1024];
    AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format);
    int i;
    int nb_renames = 0;

    if (!img->is_pipe) {
        if (img->update) {
            av_strlcpy(filename, img->path, sizeof(filename));
        } else if (img->use_strftime) {
            time_t now0;
            struct tm *tm, tmpbuf;
            time(&now0);
            tm = localtime_r(&now0, &tmpbuf);
            if (!strftime(filename, sizeof(filename), img->path, tm)) {
                av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n");
                return AVERROR(EINVAL);
            }
        } else if (av_get_frame_filename2(filename, sizeof(filename), img->path,
                                          img->img_number,
                                          AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 &&
                   img->img_number > 1) {
            av_log(s, AV_LOG_ERROR,
                   "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n",
                   img->img_number, img->path);
            return AVERROR(EINVAL);
        }
        for (i = 0; i < 4; i++) {
            snprintf(img->tmp[i], sizeof(img->tmp[i]), "%s.tmp", filename);
            av_strlcpy(img->target[i], filename, sizeof(img->target[i]));
            if (s->io_open(s, &pb[i], img->use_rename ? img->tmp[i] : filename, AVIO_FLAG_WRITE, NULL) < 0) {
                av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", img->use_rename ? img->tmp[i] : filename);
                return AVERROR(EIO);
            }

            if (!img->split_planes || i+1 >= desc->nb_components)
                break;
            filename[strlen(filename) - 1] = "UVAx"[i];
        }
        if (img->use_rename)
            nb_renames = i + 1;
    } else {
        pb[0] = s->pb;
    }

    if (img->split_planes) {
        int ysize = par->width * par->height;
        int usize = AV_CEIL_RSHIFT(par->width, desc->log2_chroma_w) * AV_CEIL_RSHIFT(par->height, desc->log2_chroma_h);
        if (desc->comp[0].depth >= 9) {
            ysize *= 2;
            usize *= 2;
        }
        avio_write(pb[0], pkt->data                , ysize);
        avio_write(pb[1], pkt->data + ysize        , usize);
        avio_write(pb[2], pkt->data + ysize + usize, usize);
        ff_format_io_close(s, &pb[1]);
        ff_format_io_close(s, &pb[2]);
        if (desc->nb_components > 3) {
            avio_write(pb[3], pkt->data + ysize + 2*usize, ysize);
            ff_format_io_close(s, &pb[3]);
        }
    } else if (img->muxer) {
        int ret;
        AVStream *st;
        AVPacket pkt2 = {0};
        AVFormatContext *fmt = NULL;

        av_assert0(!img->split_planes);

        ret = avformat_alloc_output_context2(&fmt, NULL, img->muxer, s->filename);
        if (ret < 0)
            return ret;
        st = avformat_new_stream(fmt, NULL);
        if (!st) {
            avformat_free_context(fmt);
            return AVERROR(ENOMEM);
        }
        st->id = pkt->stream_index;

        fmt->pb = pb[0];
        if ((ret = av_copy_packet(&pkt2, pkt))                            < 0 ||
                (ret = av_dup_packet(&pkt2))                                  < 0 ||
                (ret = avcodec_parameters_copy(st->codecpar, s->streams[0]->codecpar)) < 0 ||
                (ret = avformat_write_header(fmt, NULL))                      < 0 ||
                (ret = av_interleaved_write_frame(fmt, &pkt2))                < 0 ||
                (ret = av_write_trailer(fmt))                                 < 0) {
            av_packet_unref(&pkt2);
            avformat_free_context(fmt);
            return ret;
        }
        av_packet_unref(&pkt2);
        avformat_free_context(fmt);
    } else {
        avio_write(pb[0], pkt->data, pkt->size);
    }
    avio_flush(pb[0]);
    if (!img->is_pipe) {
        ff_format_io_close(s, &pb[0]);
        for (i = 0; i < nb_renames; i++) {
            int ret = ff_rename(img->tmp[i], img->target[i], s);
            if (ret < 0)
                return ret;
        }
    }

    img->img_number++;
    return 0;
}
コード例 #10
0
static int shift_data(AVFormatContext *s)
{
    int ret = 0;
    int n = 0;
    int64_t metadata_size = 0;
    FLVContext *flv = s->priv_data;
    int64_t pos, pos_end = avio_tell(s->pb);
    uint8_t *buf, *read_buf[2];
    int read_buf_id = 0;
    int read_size[2];
    AVIOContext *read_pb;

    metadata_size = flv->filepositions_count * 9 * 2 + 10; /* filepositions and times value */
    metadata_size += 2 + 13; /* filepositions String */
    metadata_size += 2 + 5; /* times String */
    metadata_size += 3; /* Object end */

    flv->keyframe_index_size = metadata_size;

    if (metadata_size < 0)
        return metadata_size;

    buf = av_malloc_array(metadata_size, 2);
    if (!buf) {
        return AVERROR(ENOMEM);
    }
    read_buf[0] = buf;
    read_buf[1] = buf + metadata_size;

    avio_seek(s->pb, flv->metadata_size_pos, SEEK_SET);
    avio_wb24(s->pb, flv->metadata_totalsize + metadata_size);

    avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET);
    avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_size);
    avio_seek(s->pb, pos_end, SEEK_SET);

    /* Shift the data: the AVIO context of the output can only be used for
     * writing, so we re-open the same output, but for reading. It also avoids
     * a read/seek/write/seek back and forth. */
    avio_flush(s->pb);
    ret = s->io_open(s, &read_pb, s->filename, AVIO_FLAG_READ, NULL);
    if (ret < 0) {
        av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for "
               "the second pass (add_keyframe_index)\n", s->filename);
        goto end;
    }

    /* mark the end of the shift to up to the last data we wrote, and get ready
     * for writing */
    pos_end = avio_tell(s->pb);
    avio_seek(s->pb, flv->keyframes_info_offset + metadata_size, SEEK_SET);

    /* start reading at where the keyframe index information will be placed */
    avio_seek(read_pb, flv->keyframes_info_offset, SEEK_SET);
    pos = avio_tell(read_pb);

    /* shift data by chunk of at most keyframe *filepositions* and *times* size */
    read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size);  \
    read_buf_id ^= 1;
    do {

        read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], metadata_size);  \
        read_buf_id ^= 1;
        n = read_size[read_buf_id];
        if (n < 0)
            break;
        avio_write(s->pb, read_buf[read_buf_id], n);
        pos += n;
    } while (pos <= pos_end);

    ff_format_io_close(s, &read_pb);

end:
    av_free(buf);
    return ret;
}
コード例 #11
0
ファイル: segment.c プロジェクト: ThomasLee969/libav
static int seg_write_header(AVFormatContext *s)
{
    SegmentContext *seg = s->priv_data;
    AVFormatContext *oc = NULL;
    int ret, i;

    seg->number = 0;
    seg->offset_time = 0;
    seg->recording_time = seg->time * 1000000;
    if (!seg->write_header_trailer)
        seg->individual_header_trailer = 0;

    if (seg->list && seg->list_type != LIST_HLS)
        if ((ret = s->io_open(s, &seg->pb, seg->list, AVIO_FLAG_WRITE, NULL)) < 0)
            goto fail;

    for (i = 0; i < s->nb_streams; i++)
        seg->has_video +=
            (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO);

    if (seg->has_video > 1)
        av_log(s, AV_LOG_WARNING,
               "More than a single video stream present, "
               "expect issues decoding it.\n");

    seg->oformat = av_guess_format(seg->format, s->filename, NULL);

    if (!seg->oformat) {
        ret = AVERROR_MUXER_NOT_FOUND;
        goto fail;
    }
    if (seg->oformat->flags & AVFMT_NOFILE) {
        av_log(s, AV_LOG_ERROR, "format %s not supported.\n",
               seg->oformat->name);
        ret = AVERROR(EINVAL);
        goto fail;
    }

    if ((ret = segment_mux_init(s)) < 0)
        goto fail;
    oc = seg->avf;

    if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
                              s->filename, seg->number++) < 0) {
        ret = AVERROR(EINVAL);
        goto fail;
    }

    if (seg->write_header_trailer) {
        if ((ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0)
            goto fail;
    } else {
        if ((ret = open_null_ctx(&oc->pb)) < 0)
            goto fail;
    }

    if ((ret = avformat_write_header(oc, NULL)) < 0) {
        ff_format_io_close(oc, &oc->pb);
        goto fail;
    }

    if (!seg->write_header_trailer) {
        close_null_ctx(oc->pb);
        if ((ret = s->io_open(s, &oc->pb, oc->filename, AVIO_FLAG_WRITE, NULL)) < 0)
            goto fail;
    }

    if (seg->list) {
        if (seg->list_type == LIST_HLS) {
            if ((ret = segment_hls_window(s, 0)) < 0)
                goto fail;
        } else {
            avio_printf(seg->pb, "%s\n", oc->filename);
            avio_flush(seg->pb);
        }
    }

fail:
    if (ret < 0)
        seg_free_context(seg);

    return ret;
}
コード例 #12
0
ファイル: segment.c プロジェクト: ThomasLee969/libav
static void seg_free_context(SegmentContext *seg)
{
    ff_format_io_close(seg->avf, &seg->pb);
    avformat_free_context(seg->avf);
    seg->avf = NULL;
}