001/*******************************************************************************
002 * Copyright (c) 2024, 2026, Olivier Ayache.  All rights reserved.
003 *
004 * This file is part of AVPKit.
005 *
006 * AVPKit is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU Lesser General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * AVPKit is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with AVPKit.  If not, see <http://www.gnu.org/licenses/>.
018 *******************************************************************************/
019
020package com.avpkit.core.io;
021
022import com.avpkit.core.io.FileProtocolHandler;
023import com.avpkit.core.io.URLProtocolManager;
024
025/**
026 * Interface that AVPKit native code calls back to for each
027 * URL.  It is assumed a new Protocol object is made
028 * per URL being read or written to.
029 * <p> 
030 * You must implement this interface if you want to register a
031 * new type of URLProtocolHandler with the {@link URLProtocolManager}.
032 * </p>
033 * <p>
034 * If you throw an exception in your implementation of this handler during
035 * a callback from within AVPKit, we will assume your method returned -1 while
036 * still in native code.  Once the stack unwinds back into Java we will
037 * re-raise your exception.
038 * </p>
039 * @see FileProtocolHandler
040 * @see NullProtocolHandler
041 * 
042 * @author aclarke
043 *
044 */
045public interface IURLProtocolHandler
046{
047  // These are the flags that can be passed to open
048  // IMPORTANT: These values must match the corresponding
049  // flags in the avio.h header file in libavformat
050  
051  /**
052   * A flag for {@link #seek(long, int)}.  Denotes positions relative to start of file.
053   */
054  public static final int SEEK_SET = 0;
055  /**
056   * A flag for {@link #seek(long, int)}.  Denotes positions relative to where the current file pointer is.
057   */
058  public static final int SEEK_CUR = 1;
059  /**
060   * A flag for {@link #seek(long, int)}.  Denotes positions relative to the end of file.
061   */
062  public static final int SEEK_END = 2;
063  /**
064   * A flag for {@link #seek(long, int)}.
065   * A special hack of FFMPEG, denotes you want to find the total size of the file.
066   */
067  public static final int SEEK_SIZE = 0x10000;
068  /**
069   * Open the file in Read Only mode.
070   */
071  public static final int URL_RDONLY_MODE = 1;
072  
073  /**
074   * Open the file in Write Only mode.
075   */
076  public static final int URL_WRONLY_MODE = 2;
077  
078  /**
079   * Implement the file in Read/Write mode.
080   */
081  public static final int URL_RDWR = 3;
082
083  /**
084   * This method gets called by FFMPEG when it opens a file.
085   * 
086   * @param url The URL to open
087   * @param flags The flags (e.g. {@link #URL_RDONLY_MODE})
088   * @return >= 0 for success; -1 for error.
089   * 
090   */
091  public int open(String url, int flags);
092
093  /**
094   * This method gets called by FFMPEG when it tries to read data.
095   * <p>
096   * For non-blocking IO, return:
097   * {@link com.avpkit.core.IError#typeToErrorNumber(com.avpkit.core.IError.Type)}
098   * pass in {@link com.avpkit.core.IError.Type#ERROR_AGAIN} for the error type.  This
099   * returns the platform specific number for EAGAIN on your platform
100   * signaling that callers should try again later.
101   * </p>
102   * <p>
103   * Alternately implementors may block until data is returning, but they should then
104   * respect the {@link Thread#isInterrupted()} setting.
105   * </p>
106   * 
107   * @param buf The buffer to write your data to.
108   * @param size The number of bytes in buf data available for you to write the data that FFMPEG will read.
109   * @return 0 for end of file, else number of bytes you wrote to the buffer, or -1 if error.
110   */
111  public int read(byte[] buf, int size);
112
113  /**
114   * This method gets called by FFMPEG when it tries to write data.
115   * <p>
116   * For non-blocking IO, return:
117   * {@link com.avpkit.core.IError#typeToErrorNumber(com.avpkit.core.IError.Type)}
118   * pass in {@link com.avpkit.core.IError.Type#ERROR_AGAIN} for the error type.  This
119   * returns the platform specific number for EAGAIN on your platform
120   * signaling that callers should try again later.
121   * </p>
122   * <p>
123   * Alternately implementators may block until data is returning, but they should then
124   * respect the {@link Thread#isInterrupted()} setting.
125   * </p>
126   * 
127   * @param buf The data you should write.
128   * @param size The number of bytes in buf.
129   * @return 0 for end of file, else number of bytes you read from buf, or -1 if error.
130   */
131  public int write(byte[] buf, int size);
132
133  /**
134   * A request from FFMPEG to seek to a position in the stream.
135   * 
136   * @param offset The offset in bytes.
137   * @param whence Where that offset is relative to.  Follow the C stdlib fseek() conventions EXCEPT
138   *   {@link #SEEK_SIZE} should return back the size of the stream in bytes if known without adjusting
139   *   the seek pointer.
140   * @return -1 if not supported, else the position relative to whence
141   */
142  public long seek(long offset, int whence);
143
144  /**
145   * A request to close() from FFMPEG
146   * 
147   * @return -1 on error; else >= 0
148   */
149  public int close();
150
151  /**
152   * Special callback made by AVPKit in order to determine if your
153   * stream supports streaming.
154   *
155   * <p>
156   * 
157   * If this method returns true, AVPKit will assume it cannot seek backwards
158   * in this container.
159   * </p>
160   * <p>
161   * 
162   * This has one main practical consequence.  When writing it means certain container formats (e.g. the MOV
163   * container) will not be usable as it requires seeking
164   * back to the start of a file to write MOV required header information once
165   * the entire file has been encoded.
166   * 
167   * </p>
168   * <p>
169   * 
170   * But if your medium is streaming, you'll want to return true for this,
171   * and then FFMPEG will not attempt to seek back in time.
172   * 
173   * </p>
174   *  
175   * @param url The URL that would be passed to {@link #open(String, int)}
176   * @param flags The flags that would be passed to {@link #open(String, int)}
177   * @return true if you can stream that URL; false if not.
178   */
179  public boolean isStreamed(String url, int flags);
180}