- 论坛徽章:
- 2
|
本帖最后由 lhd666 于 2017-02-16 10:04 编辑
以前没搞过视频相关的东西,现在需要使用ffmpeg在ceph对象存储上进行转码。ffmpeg自带示例avio_reading.c演示了怎么自定义输入流,我参照它成功从ceph对象存储中读取到数据并解码,但是又该怎么自定义输出流呢?
ffmpeg示例中,也有不使用AVFormatContext,用fwrite()写入AVPacket的示例,那么我只需要把fwrite()替换成rados的写入操作即可,但是不知道avformat_write_header()和av_write_trailer()这两个api写入的数据该怎么使用fwrite()写入,归根结底还是对ffmpeg不熟,网上资料又少。
下面是自定义输入流的代码:
- struct ceph_handler {
- rados_t cluster;
- rados_ioctx_t io;
- uint64_t off;
- char *objname;
- };
- struct ceph_handler *ceph_handler_create(const char * const clustername,
- const char * const username,
- uint64_t flags,
- const char * const conf,
- const char * const poolname,
- const char * const objname)
- {
- struct ceph_handler *handler;
- int err;
- handler = malloc(sizeof(*handler));
- if (!handler)
- return NULL;
- err = rados_create2(&handler->cluster, clustername, username, flags);
- if (err < 0) {
- free(handler);
- return NULL;
- }
- err = rados_conf_read_file(handler->cluster, conf);
- if (err < 0) {
- rados_shutdown(handler->cluster);
- free(handler);
- return NULL;
- }
- err = rados_connect(handler->cluster);
- if (err < 0) {
- rados_shutdown(handler->cluster);
- free(handler);
- return NULL;
- }
- err = rados_ioctx_create(handler->cluster, poolname, &handler->io);
- if (err < 0) {
- rados_shutdown(handler->cluster);
- free(handler);
- return NULL;
- }
- handler->objname = strdup(objname);
- if (!handler->objname) {
- rados_ioctx_destroy(handler->io);
- rados_shutdown(handler->cluster);
- free(handler);
- return NULL;
- }
- handler->off = 0;
- return handler;
- }
- void ceph_handler_destroy(struct ceph_handler *handler)
- {
- rados_ioctx_destroy(handler->io);
- rados_shutdown(handler->cluster);
- free(handler->objname);
- free(handler);
- }
- static int read_packet(void *opaque, uint8_t *buf, int buf_size)
- {
- struct ceph_handler *handler = opaque;
- int nr;
- nr = rados_read(handler->io, handler->objname, (char *)buf, buf_size, handler->off);
- if (nr < 0)
- errno = -nr;
- else
- handler->off += nr;
- return nr;
- }
- static int write_packet(void *opaque, uint8_t *buf, int buf_size)
- {
- struct ceph_handler *handler = opaque;
- int err;
- /* 成功时返回0,而非写入字节数 */
- err = rados_write(handler->io, handler->objname, (char *)buf, buf_size, handler->off);
- if (err)
- errno = - err;
- else
- handler->off += buf_size;
- return err ? err : buf_size;
- }
- static int64_t seek(void *opaque, int64_t offset, int whence)
- {
- struct ceph_handler *handler = opaque;
- uint64_t size;
- time_t mtime;
- int err;
- switch (whence) {
- case SEEK_SET:
- handler->off = offset;
- break;
- case SEEK_CUR:
- handler->off += offset;
- break;
- case SEEK_END:
- err = rados_stat(handler->io, handler->objname, &size, &mtime);
- if (err < 0) {
- errno = - err;
- return -1;
- }
- if (size < offset)
- handler->off = 0;
- else
- handler->off = size - offset;
- }
- return handler->off;
- }
- static int open_input_file(const char *filename)
- {
- AVIOContext *avio_ctx = NULL;
- uint8_t *avio_ctx_buffer = NULL;
- size_t avio_ctx_buffer_size = 1 << 2;
- struct ceph_handler *handler = NULL;
- unsigned int i;
- int ret;
- ifmt_ctx = NULL;
-
- handler = ceph_handler_create("ceph", "client.admin", 0,
- "ceph.conf", "mypool", filename);
- if (!handler)
- return -1;
- ifmt_ctx = avformat_alloc_context();
- if (!ifmt_ctx)
- goto err;
- avio_ctx_buffer = av_malloc(avio_ctx_buffer_size);
- if (!avio_ctx_buffer)
- goto err;
- avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,
- 0, handler, read_packet, write_packet,
- seek);
- if (!avio_ctx)
- goto err;
- ifmt_ctx->pb = avio_ctx;
- ret = avformat_open_input(&ifmt_ctx, NULL, NULL, NULL);
- if (ret < 0)
- goto err;
- ret = avformat_find_stream_info(ifmt_ctx, NULL);
- if (ret < 0)
- goto err;
- for (i = 0; i < ifmt_ctx->nb_streams; i++) {
- AVStream *stream;
- AVCodecContext *codec_ctx;
- stream = ifmt_ctx->streams[i];
- codec_ctx = stream->codec;
- /* Reencode video & audio and remux subtitles etc. */
- if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
- codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
- /* Open decoder */
- ret = avcodec_open2(codec_ctx,
- avcodec_find_decoder(codec_ctx->codec_id), NULL);
- if (ret < 0)
- goto err;
- }
- }
-
- av_dump_format(ifmt_ctx, 0, filename, 0);
- return 0;
- err:
- if (ifmt_ctx)
- avformat_close_input(&ifmt_ctx);
- ifmt_ctx = NULL;
- if (handler)
- ceph_handler_destroy(handler);
- if (avio_ctx) {
- av_freep(&avio_ctx->buffer);
- av_freep(&avio_ctx);
- }
- return -1;
- }
复制代码
|
|