source: trunk/ff_dataref.c @ 969

Revision 969, 5.8 KB checked in by astrange, 6 years ago (diff)

Replace trunk with 1.1 branch, keeping ffmpeg compatibility patches.
This will probably break local changes.

Line 
1/*****************************************************************************
2*
3*  Avi Import Component dataref interface for libavformat
4*
5*  Copyright(C) 2006 Christoph Naegeli <chn1@mac.com>
6*
7*  This library is free software; you can redistribute it and/or
8*  modify it under the terms of the GNU Lesser General Public
9*  License as published by the Free Software Foundation; either
10*  version 2.1 of the License, or (at your option) any later version.
11
12*  This library is distributed in the hope that it will be useful,
13*  but WITHOUT ANY WARRANTY; without even the implied warranty of
14*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*  Lesser General Public License for more details.
16
17*  You should have received a copy of the GNU Lesser General Public
18*  License along with this library; if not, write to the Free Software
19*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20*
21****************************************************************************/
22
23#include "avformat.h"
24
25#include <QuickTime/QuickTime.h>
26
27struct _dataref_private {
28        Handle dataRef;
29        OSType dataRefType;
30        DataHandler dh;
31        int64_t pos;
32        int64_t size;
33        unsigned char supportsWideOffsets;
34};
35typedef struct _dataref_private dataref_private;
36
37/* DataRef Wrapper for QuickTime */
38
39/* !!! THIS FUNCTION ASSUMES h->priv_data IS VALID in contrary to the other open functions
40* found in ffmpeg */
41static int dataref_open(URLContext *h, const char *filename, int flags)
42{
43        ComponentResult result;
44        dataref_private *private;
45        wide fsize;
46        long access = 0;
47       
48        if(flags & URL_RDWR) {
49                access = kDataHCanRead | kDataHCanWrite;
50        } else if(flags & URL_WRONLY) {
51                access = kDataHCanWrite;
52        } else {
53                access = kDataHCanRead;
54        }
55       
56        private = h->priv_data;
57        result = OpenAComponent(GetDataHandler(private->dataRef, private->dataRefType, access), &private->dh);
58        require_noerr(result,bail);
59       
60        result = DataHSetDataRef(private->dh, private->dataRef);
61        require_noerr(result,bail);
62       
63        if(access & kDataHCanRead) {
64                result = DataHOpenForRead(private->dh);
65                require_noerr(result,bail);
66        }
67        if(access & kDataHCanWrite) {
68                result = DataHOpenForWrite(private->dh);
69                require_noerr(result,bail);
70        }
71       
72        private->pos = 0ll;
73        private->size = 0ll;
74       
75        result = DataHGetFileSize64(private->dh, &fsize);
76        if(result == noErr) {
77                private->size = (int64_t)fsize.lo;
78                private->size += (int64_t)fsize.hi << 32;
79                // Our data handler supports wide offsets. Remember for later use.
80                private->supportsWideOffsets = 1;
81        } else {
82                long size32;
83                result = DataHGetFileSize(private->dh, &size32);
84                require_noerr(result, bail);
85                private->size = size32;
86        }
87       
88bail:
89                return result;
90} /* dataref_open() */
91
92static int dataref_read(URLContext *h, unsigned char *buf, int size)
93{
94        int result;
95        int64_t read;
96
97        dataref_private *p = (dataref_private*)h->priv_data;
98       
99        read = p->size - p->pos;
100        read = (read < size) ? read : size;
101       
102        if(p->supportsWideOffsets) {
103                wide offset;
104                offset.hi = p->pos >> 32;
105                offset.lo = (UInt32)p->pos;
106               
107                result = DataHScheduleData64(p->dh, (Ptr)buf, &offset, (long)read, 0, NULL, NULL);
108                if (result == badComponentSelector && offset.hi == 0) {
109                        result = DataHScheduleData(p->dh, (Ptr)buf, offset.lo, (long)read, 0, NULL, NULL);
110                }
111        } else {
112                result = DataHScheduleData(p->dh, (Ptr)buf, (long)p->pos, (long)read, 0, NULL, NULL);
113        }
114       
115        if(result != noErr) {
116                read = -1;
117                goto bail;
118        }
119       
120        p->pos += read;
121       
122bail:
123                return (int)read;
124} /* dataref_read() */
125
126static int dataref_write(URLContext *h, unsigned char *buf, int size)
127{
128        int result;
129        int written = size;
130        dataref_private *p = (dataref_private*)h->priv_data;
131       
132        if(p->supportsWideOffsets) {
133                wide offset;
134                offset.hi = p->pos >> 32;
135                offset.lo = (UInt32)p->pos;
136               
137                result = DataHWrite64(p->dh, (Ptr)buf, &offset, size, NULL, 0);
138        } else {
139                result = DataHWrite(p->dh, (Ptr)buf, (long)p->pos, size, NULL, 0);
140        }
141       
142        if(result != noErr) {
143                written = -1;
144                goto bail;
145        }
146       
147        p->pos += written;
148       
149bail:
150                return written;
151} /* dataref_write() */
152
153static int64_t dataref_seek(URLContext *h, int64_t pos, int whence)
154{
155        dataref_private *p = (dataref_private*)h->priv_data;
156       
157        switch(whence) {
158                case SEEK_SET:
159                        p->pos = pos;
160                        break;
161                case SEEK_CUR:
162                        p->pos += pos;
163                        break;
164                case SEEK_END:
165                        p->pos = p->size + pos;
166                        break;
167                case AVSEEK_SIZE:
168                        return p->size;
169                default:
170                        return -1;
171        }
172       
173        return p->pos;
174} /* dataref_seek() */
175
176static int dataref_close(URLContext *h)
177{
178        dataref_private *p = (dataref_private*)h->priv_data;
179       
180        CloseComponent(p->dh);
181        p->dh = 0;
182        p->pos = 0;
183        p->size = 0;
184       
185        av_free(p);
186        h->priv_data = NULL;
187       
188        return 0;
189} /* dataref_close() */
190
191URLProtocol dataref_protocol = {
192    "Data Ref",
193    dataref_open,
194    dataref_read,
195    dataref_write,
196    dataref_seek,
197    dataref_close,
198};
199
200/* This is the public function to open bytecontext withs datarefs */
201OSStatus url_open_dataref(ByteIOContext **pb, Handle dataRef, OSType dataRefType, DataHandler *dataHandler, Boolean *wideSupport, int64_t *dataSize)
202{
203        URLContext *uc;
204        URLProtocol *up;
205        OSStatus err;
206        dataref_private *private;
207       
208        private = av_mallocz(sizeof(dataref_private));
209        private->dataRef = dataRef;
210        private->dataRefType = dataRefType;
211       
212        up = &dataref_protocol;
213       
214        uc = av_mallocz(sizeof(URLContext));
215        if(!uc) {
216                err = -ENOMEM;
217                return err;
218        }
219        uc->filename = NULL;
220        uc->prot = up;
221        uc->flags = URL_RDONLY; // we're just using the read access...
222        uc->is_streamed = 0; // not streamed...
223        uc->max_packet_size = 0; // stream file
224        uc->priv_data = private;
225       
226        err = up->url_open(uc, uc->filename, URL_RDONLY);
227               
228        if(err < 0) {
229                av_free(uc);
230                return err;
231        }
232        err = url_fdopen(pb, uc);
233        if(err < 0) {
234                url_close(uc);
235                return err;
236        }
237       
238        if(dataHandler)
239                *dataHandler = private->dh;
240       
241        if(wideSupport)
242                *wideSupport = private->supportsWideOffsets;
243       
244        if(dataSize)
245                *dataSize = private->size;     
246       
247        return noErr;
248} /* url_open_dataref() */
Note: See TracBrowser for help on using the repository browser.