FFmpegKit Android API  4.4
saf_wrapper.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020-2021 Taner Sener
3  *
4  * This file is part of FFmpegKit.
5  *
6  * FFmpegKit is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * FFmpegKit is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <sys/stat.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 
24 #include "config.h"
25 #include "libavformat/avformat.h"
26 #include "libavutil/avstring.h"
27 
28 #include "saf_wrapper.h"
29 
31 void closeParcelFileDescriptor(int fd);
32 
33 // in these wrappers, we call the original functions, so we remove the shadow defines
34 #undef avio_closep
35 #undef avformat_close_input
36 #undef avio_open
37 #undef avio_open2
38 #undef avformat_open_input
39 
40 static int fd_read_packet(void* opaque, uint8_t* buf, int buf_size) {
41  return read(*(int*)opaque, buf, buf_size);
42 }
43 
44 static int fd_write_packet(void* opaque, uint8_t* buf, int buf_size) {
45  return write(*(int*)opaque, buf, buf_size);
46 }
47 
48 static int64_t fd_seek(void *opaque, int64_t offset, int whence) {
49  int *fd = opaque;
50 
51  if (*fd < 0) {
52  return AVERROR(EINVAL);
53  }
54 
55  int64_t ret;
56  if (whence == AVSEEK_SIZE) {
57  struct stat st;
58  ret = fstat(*fd, &st);
59  return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 : st.st_size);
60  }
61 
62  ret = lseek(*fd, offset, whence);
63 
64  return ret < 0 ? AVERROR(errno) : ret;
65 }
66 
67 /*
68  * returns NULL if the filename is not of expected format (e.g. 'saf:72/video.md4')
69  */
70 static AVIOContext *create_fd_avio_context(const char *filename, int flags) {
71  int fd = -1;
72  const char* fd_ptr = NULL;
73 
74  if (av_strstart(filename, "saf:", &fd_ptr)) {
75  char *final;
76  fd = strtol(fd_ptr, &final, 10);
77  if (fd_ptr == final) { /* No digits found */
78  fd = -1;
79  }
80  }
81 
82  if (fd >= 0) {
83  int *opaque = av_mallocz(sizeof(int));
84  *opaque = fd;
85  int write_flag = flags & AVIO_FLAG_WRITE ? 1 : 0;
86  return avio_alloc_context(av_malloc(4096), 4096, write_flag, opaque, fd_read_packet, write_flag ? fd_write_packet : NULL, fd_seek);
87  }
88 
89  return NULL;
90 }
91 
92 static void close_fd_avio_context(AVIOContext *ctx) {
93  if (ctx) {
94  if (fd_seek(ctx->opaque, 0, AVSEEK_SIZE) >= 0) {
95  int *fd = ctx->opaque;
97  av_freep(&fd);
98  }
99  ctx->opaque = NULL;
100  }
101 }
102 
103 int android_avformat_open_input(AVFormatContext **ps, const char *filename,
104  ff_const59 AVInputFormat *fmt, AVDictionary **options) {
105  if (!(*ps) && !(*ps = avformat_alloc_context()))
106  return AVERROR(ENOMEM);
107 
108  (*ps)->pb = create_fd_avio_context(filename, AVIO_FLAG_READ);
109 
110  return avformat_open_input(ps, filename, fmt, options);
111 }
112 
113 int android_avio_open2(AVIOContext **s, const char *filename, int flags,
114  const AVIOInterruptCB *int_cb, AVDictionary **options) {
115  AVIOContext *fd_context = create_fd_avio_context(filename, flags);
116 
117  if (fd_context) {
118  *s = fd_context;
119  return 0;
120  }
121 
122  return avio_open2(s, filename, flags, int_cb, options);
123 }
124 
125 int android_avio_open(AVIOContext **s, const char *url, int flags) {
126  return android_avio_open2(s, url, flags, NULL, NULL);
127 }
128 
129 int android_avio_closep(AVIOContext **s) {
131  return avio_closep(s);
132 }
133 
134 void android_avformat_close_input(AVFormatContext **ps) {
135  if (*ps && (*ps)->pb) {
136  close_fd_avio_context((*ps)->pb);
137  }
139 }
__thread const AVIOInterruptCB int_cb
int android_avformat_open_input(AVFormatContext **ps, const char *filename, ff_const59 AVInputFormat *fmt, AVDictionary **options)
Definition: saf_wrapper.c:103
static AVIOContext * create_fd_avio_context(const char *filename, int flags)
Definition: saf_wrapper.c:70
int android_avio_closep(AVIOContext **s)
Definition: saf_wrapper.c:129
int android_avio_open2(AVIOContext **s, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Definition: saf_wrapper.c:113
void android_avformat_close_input(AVFormatContext **ps)
Definition: saf_wrapper.c:134
static void close_fd_avio_context(AVIOContext *ctx)
Definition: saf_wrapper.c:92
static int fd_read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: saf_wrapper.c:40
int android_avio_open(AVIOContext **s, const char *url, int flags)
Definition: saf_wrapper.c:125
static int64_t fd_seek(void *opaque, int64_t offset, int whence)
Definition: saf_wrapper.c:48
static int fd_write_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: saf_wrapper.c:44
void closeParcelFileDescriptor(int fd)
Definition: ffmpegkit.c:565
#define avformat_open_input
Definition: saf_wrapper.h:44
#define avio_open2
Definition: saf_wrapper.h:40
#define avio_closep
Definition: saf_wrapper.h:30
#define avformat_close_input
Definition: saf_wrapper.h:33