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}