├── .gitignore ├── .gitmodules ├── COPYING.LGPLv2.1 ├── COPYING.LGPLv3 ├── FFmpegWrapper.podspec ├── FFmpegWrapper.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── chrisbal.xcuserdatad │ └── xcschemes │ ├── FFmpegWrapper.xcscheme │ └── xcschememanagement.plist ├── FFmpegWrapper ├── FFBitstreamFilter.h ├── FFBitstreamFilter.m ├── FFFile.h ├── FFFile.m ├── FFInputFile.h ├── FFInputFile.m ├── FFInputStream.h ├── FFInputStream.m ├── FFOutputFile.h ├── FFOutputFile.m ├── FFOutputStream.h ├── FFOutputStream.m ├── FFStream.h ├── FFStream.m ├── FFUtilities.h ├── FFUtilities.m ├── FFmpegWrapper-Prefix.pch ├── FFmpegWrapper.h └── FFmpegWrapper.m ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build 3 | *.mode1v3 4 | *.pbxuser 5 | project.xcworkspace 6 | xcuserdata 7 | .svn 8 | DerivedData 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Submodules/FFmpeg-iOS"] 2 | path = Submodules/FFmpeg-iOS 3 | url = git@github.com:chrisballinger/FFmpeg-iOS.git 4 | -------------------------------------------------------------------------------- /COPYING.LGPLv2.1: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | -------------------------------------------------------------------------------- /COPYING.LGPLv3: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /FFmpegWrapper.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "FFmpegWrapper" 3 | s.version = "1.0" 4 | s.summary = "A lightweight Objective-C wrapper for some FFmpeg libav functions" 5 | s.homepage = "https://github.com/OpenWatch/FFmpegWrapper" 6 | s.license = 'LGPLv2.1+' 7 | s.author = { "Chris Ballinger" => "chris@openwatch.net" } 8 | s.platform = :ios, '6.0' 9 | s.source = { :git => "https://github.com/OpenWatch/FFmpegWrapper.git", :tag => "1.0"} 10 | s.source_files = 'FFmpegWrapper/*.{h,m}' 11 | s.ios.deployment_target = '6.0' 12 | s.requires_arc = true 13 | 14 | s.dependency 'FFmpeg', '~> 2.2' 15 | end 16 | -------------------------------------------------------------------------------- /FFmpegWrapper.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D95F88DA17E8C259000ADE35 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D95F88D917E8C259000ADE35 /* Foundation.framework */; }; 11 | D95F88DF17E8C259000ADE35 /* FFmpegWrapper.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = D95F88DE17E8C259000ADE35 /* FFmpegWrapper.h */; }; 12 | D95F88E117E8C259000ADE35 /* FFmpegWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = D95F88E017E8C259000ADE35 /* FFmpegWrapper.m */; }; 13 | D95F88E817E8C259000ADE35 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D95F88E717E8C259000ADE35 /* XCTest.framework */; }; 14 | D95F88E917E8C259000ADE35 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D95F88D917E8C259000ADE35 /* Foundation.framework */; }; 15 | D95F88EB17E8C259000ADE35 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D95F88EA17E8C259000ADE35 /* UIKit.framework */; }; 16 | D95F88EE17E8C259000ADE35 /* libFFmpegWrapper.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D95F88D617E8C259000ADE35 /* libFFmpegWrapper.a */; }; 17 | D95F88F417E8C259000ADE35 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D95F88F217E8C259000ADE35 /* InfoPlist.strings */; }; 18 | D95F88F617E8C259000ADE35 /* FFmpegWrapperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D95F88F517E8C259000ADE35 /* FFmpegWrapperTests.m */; }; 19 | D9CF4B9D17E8CA1A00E7EE87 /* libavcodec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9CF4B9617E8CA1A00E7EE87 /* libavcodec.a */; }; 20 | D9CF4B9E17E8CA1A00E7EE87 /* libavdevice.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9CF4B9717E8CA1A00E7EE87 /* libavdevice.a */; }; 21 | D9CF4B9F17E8CA1A00E7EE87 /* libavfilter.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9CF4B9817E8CA1A00E7EE87 /* libavfilter.a */; }; 22 | D9CF4BA017E8CA1A00E7EE87 /* libavformat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9CF4B9917E8CA1A00E7EE87 /* libavformat.a */; }; 23 | D9CF4BA117E8CA1A00E7EE87 /* libavutil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9CF4B9A17E8CA1A00E7EE87 /* libavutil.a */; }; 24 | D9CF4BA217E8CA1A00E7EE87 /* libswresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9CF4B9B17E8CA1A00E7EE87 /* libswresample.a */; }; 25 | D9CF4BA317E8CA1A00E7EE87 /* libswscale.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D9CF4B9C17E8CA1A00E7EE87 /* libswscale.a */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | D95F88EC17E8C259000ADE35 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = D95F88CE17E8C259000ADE35 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = D95F88D517E8C259000ADE35; 34 | remoteInfo = FFmpegWrapper; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXCopyFilesBuildPhase section */ 39 | D95F88D417E8C259000ADE35 /* CopyFiles */ = { 40 | isa = PBXCopyFilesBuildPhase; 41 | buildActionMask = 2147483647; 42 | dstPath = "include/$(PRODUCT_NAME)"; 43 | dstSubfolderSpec = 16; 44 | files = ( 45 | D95F88DF17E8C259000ADE35 /* FFmpegWrapper.h in CopyFiles */, 46 | ); 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | /* End PBXCopyFilesBuildPhase section */ 50 | 51 | /* Begin PBXFileReference section */ 52 | D95F88D617E8C259000ADE35 /* libFFmpegWrapper.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFFmpegWrapper.a; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | D95F88D917E8C259000ADE35 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 54 | D95F88DD17E8C259000ADE35 /* FFmpegWrapper-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FFmpegWrapper-Prefix.pch"; sourceTree = ""; }; 55 | D95F88DE17E8C259000ADE35 /* FFmpegWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FFmpegWrapper.h; sourceTree = ""; }; 56 | D95F88E017E8C259000ADE35 /* FFmpegWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FFmpegWrapper.m; sourceTree = ""; }; 57 | D95F88E617E8C259000ADE35 /* FFmpegWrapperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FFmpegWrapperTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | D95F88E717E8C259000ADE35 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 59 | D95F88EA17E8C259000ADE35 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 60 | D95F88F117E8C259000ADE35 /* FFmpegWrapperTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FFmpegWrapperTests-Info.plist"; sourceTree = ""; }; 61 | D95F88F317E8C259000ADE35 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 62 | D95F88F517E8C259000ADE35 /* FFmpegWrapperTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FFmpegWrapperTests.m; sourceTree = ""; }; 63 | D9CF4B4217E8CA1A00E7EE87 /* avcodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avcodec.h; sourceTree = ""; }; 64 | D9CF4B4317E8CA1A00E7EE87 /* avfft.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avfft.h; sourceTree = ""; }; 65 | D9CF4B4417E8CA1A00E7EE87 /* dxva2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dxva2.h; sourceTree = ""; }; 66 | D9CF4B4517E8CA1A00E7EE87 /* old_codec_ids.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = old_codec_ids.h; sourceTree = ""; }; 67 | D9CF4B4617E8CA1A00E7EE87 /* vaapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vaapi.h; sourceTree = ""; }; 68 | D9CF4B4717E8CA1A00E7EE87 /* vda.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vda.h; sourceTree = ""; }; 69 | D9CF4B4817E8CA1A00E7EE87 /* vdpau.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vdpau.h; sourceTree = ""; }; 70 | D9CF4B4917E8CA1A00E7EE87 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 71 | D9CF4B4A17E8CA1A00E7EE87 /* xvmc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xvmc.h; sourceTree = ""; }; 72 | D9CF4B4C17E8CA1A00E7EE87 /* avdevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avdevice.h; sourceTree = ""; }; 73 | D9CF4B4D17E8CA1A00E7EE87 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 74 | D9CF4B4F17E8CA1A00E7EE87 /* asrc_abuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asrc_abuffer.h; sourceTree = ""; }; 75 | D9CF4B5017E8CA1A00E7EE87 /* avcodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avcodec.h; sourceTree = ""; }; 76 | D9CF4B5117E8CA1A00E7EE87 /* avfilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avfilter.h; sourceTree = ""; }; 77 | D9CF4B5217E8CA1A00E7EE87 /* avfiltergraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avfiltergraph.h; sourceTree = ""; }; 78 | D9CF4B5317E8CA1A00E7EE87 /* buffersink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffersink.h; sourceTree = ""; }; 79 | D9CF4B5417E8CA1A00E7EE87 /* buffersrc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffersrc.h; sourceTree = ""; }; 80 | D9CF4B5517E8CA1A00E7EE87 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 81 | D9CF4B5717E8CA1A00E7EE87 /* avformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avformat.h; sourceTree = ""; }; 82 | D9CF4B5817E8CA1A00E7EE87 /* avio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avio.h; sourceTree = ""; }; 83 | D9CF4B5917E8CA1A00E7EE87 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 84 | D9CF4B5B17E8CA1A00E7EE87 /* adler32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adler32.h; sourceTree = ""; }; 85 | D9CF4B5C17E8CA1A00E7EE87 /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = ""; }; 86 | D9CF4B5D17E8CA1A00E7EE87 /* attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attributes.h; sourceTree = ""; }; 87 | D9CF4B5E17E8CA1A00E7EE87 /* audio_fifo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_fifo.h; sourceTree = ""; }; 88 | D9CF4B5F17E8CA1A00E7EE87 /* audioconvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audioconvert.h; sourceTree = ""; }; 89 | D9CF4B6017E8CA1A00E7EE87 /* avassert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avassert.h; sourceTree = ""; }; 90 | D9CF4B6117E8CA1A00E7EE87 /* avconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avconfig.h; sourceTree = ""; }; 91 | D9CF4B6217E8CA1A00E7EE87 /* avstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avstring.h; sourceTree = ""; }; 92 | D9CF4B6317E8CA1A00E7EE87 /* avutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avutil.h; sourceTree = ""; }; 93 | D9CF4B6417E8CA1A00E7EE87 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = ""; }; 94 | D9CF4B6517E8CA1A00E7EE87 /* blowfish.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blowfish.h; sourceTree = ""; }; 95 | D9CF4B6617E8CA1A00E7EE87 /* bprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bprint.h; sourceTree = ""; }; 96 | D9CF4B6717E8CA1A00E7EE87 /* bswap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bswap.h; sourceTree = ""; }; 97 | D9CF4B6817E8CA1A00E7EE87 /* buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffer.h; sourceTree = ""; }; 98 | D9CF4B6917E8CA1A00E7EE87 /* channel_layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = channel_layout.h; sourceTree = ""; }; 99 | D9CF4B6A17E8CA1A00E7EE87 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; 100 | D9CF4B6B17E8CA1A00E7EE87 /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = ""; }; 101 | D9CF4B6C17E8CA1A00E7EE87 /* crc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc.h; sourceTree = ""; }; 102 | D9CF4B6D17E8CA1A00E7EE87 /* dict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dict.h; sourceTree = ""; }; 103 | D9CF4B6E17E8CA1A00E7EE87 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = ""; }; 104 | D9CF4B6F17E8CA1A00E7EE87 /* eval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eval.h; sourceTree = ""; }; 105 | D9CF4B7017E8CA1A00E7EE87 /* fifo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fifo.h; sourceTree = ""; }; 106 | D9CF4B7117E8CA1A00E7EE87 /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = ""; }; 107 | D9CF4B7217E8CA1A00E7EE87 /* frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = frame.h; sourceTree = ""; }; 108 | D9CF4B7317E8CA1A00E7EE87 /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = ""; }; 109 | D9CF4B7417E8CA1A00E7EE87 /* imgutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgutils.h; sourceTree = ""; }; 110 | D9CF4B7517E8CA1A00E7EE87 /* intfloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intfloat.h; sourceTree = ""; }; 111 | D9CF4B7617E8CA1A00E7EE87 /* intfloat_readwrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intfloat_readwrite.h; sourceTree = ""; }; 112 | D9CF4B7717E8CA1A00E7EE87 /* intreadwrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intreadwrite.h; sourceTree = ""; }; 113 | D9CF4B7817E8CA1A00E7EE87 /* lfg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lfg.h; sourceTree = ""; }; 114 | D9CF4B7917E8CA1A00E7EE87 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; 115 | D9CF4B7A17E8CA1A00E7EE87 /* lzo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lzo.h; sourceTree = ""; }; 116 | D9CF4B7B17E8CA1A00E7EE87 /* mathematics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mathematics.h; sourceTree = ""; }; 117 | D9CF4B7C17E8CA1A00E7EE87 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = ""; }; 118 | D9CF4B7D17E8CA1A00E7EE87 /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = ""; }; 119 | D9CF4B7E17E8CA1A00E7EE87 /* murmur3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = murmur3.h; sourceTree = ""; }; 120 | D9CF4B7F17E8CA1A00E7EE87 /* old_pix_fmts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = old_pix_fmts.h; sourceTree = ""; }; 121 | D9CF4B8017E8CA1A00E7EE87 /* opt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opt.h; sourceTree = ""; }; 122 | D9CF4B8117E8CA1A00E7EE87 /* parseutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parseutils.h; sourceTree = ""; }; 123 | D9CF4B8217E8CA1A00E7EE87 /* pixdesc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixdesc.h; sourceTree = ""; }; 124 | D9CF4B8317E8CA1A00E7EE87 /* pixfmt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixfmt.h; sourceTree = ""; }; 125 | D9CF4B8417E8CA1A00E7EE87 /* random_seed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random_seed.h; sourceTree = ""; }; 126 | D9CF4B8517E8CA1A00E7EE87 /* rational.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rational.h; sourceTree = ""; }; 127 | D9CF4B8617E8CA1A00E7EE87 /* ripemd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ripemd.h; sourceTree = ""; }; 128 | D9CF4B8717E8CA1A00E7EE87 /* samplefmt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = samplefmt.h; sourceTree = ""; }; 129 | D9CF4B8817E8CA1A00E7EE87 /* sha.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha.h; sourceTree = ""; }; 130 | D9CF4B8917E8CA1A00E7EE87 /* sha512.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha512.h; sourceTree = ""; }; 131 | D9CF4B8A17E8CA1A00E7EE87 /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = ""; }; 132 | D9CF4B8B17E8CA1A00E7EE87 /* timecode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timecode.h; sourceTree = ""; }; 133 | D9CF4B8C17E8CA1A00E7EE87 /* timestamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timestamp.h; sourceTree = ""; }; 134 | D9CF4B8D17E8CA1A00E7EE87 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 135 | D9CF4B8E17E8CA1A00E7EE87 /* xtea.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xtea.h; sourceTree = ""; }; 136 | D9CF4B9017E8CA1A00E7EE87 /* swresample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swresample.h; sourceTree = ""; }; 137 | D9CF4B9117E8CA1A00E7EE87 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 138 | D9CF4B9317E8CA1A00E7EE87 /* swscale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swscale.h; sourceTree = ""; }; 139 | D9CF4B9417E8CA1A00E7EE87 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; 140 | D9CF4B9617E8CA1A00E7EE87 /* libavcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavcodec.a; sourceTree = ""; }; 141 | D9CF4B9717E8CA1A00E7EE87 /* libavdevice.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavdevice.a; sourceTree = ""; }; 142 | D9CF4B9817E8CA1A00E7EE87 /* libavfilter.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavfilter.a; sourceTree = ""; }; 143 | D9CF4B9917E8CA1A00E7EE87 /* libavformat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavformat.a; sourceTree = ""; }; 144 | D9CF4B9A17E8CA1A00E7EE87 /* libavutil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavutil.a; sourceTree = ""; }; 145 | D9CF4B9B17E8CA1A00E7EE87 /* libswresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libswresample.a; sourceTree = ""; }; 146 | D9CF4B9C17E8CA1A00E7EE87 /* libswscale.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libswscale.a; sourceTree = ""; }; 147 | /* End PBXFileReference section */ 148 | 149 | /* Begin PBXFrameworksBuildPhase section */ 150 | D95F88D317E8C259000ADE35 /* Frameworks */ = { 151 | isa = PBXFrameworksBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | D9CF4BA117E8CA1A00E7EE87 /* libavutil.a in Frameworks */, 155 | D9CF4B9F17E8CA1A00E7EE87 /* libavfilter.a in Frameworks */, 156 | D95F88DA17E8C259000ADE35 /* Foundation.framework in Frameworks */, 157 | D9CF4B9E17E8CA1A00E7EE87 /* libavdevice.a in Frameworks */, 158 | D9CF4BA317E8CA1A00E7EE87 /* libswscale.a in Frameworks */, 159 | D9CF4BA017E8CA1A00E7EE87 /* libavformat.a in Frameworks */, 160 | D9CF4BA217E8CA1A00E7EE87 /* libswresample.a in Frameworks */, 161 | D9CF4B9D17E8CA1A00E7EE87 /* libavcodec.a in Frameworks */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | D95F88E317E8C259000ADE35 /* Frameworks */ = { 166 | isa = PBXFrameworksBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | D95F88E817E8C259000ADE35 /* XCTest.framework in Frameworks */, 170 | D95F88EB17E8C259000ADE35 /* UIKit.framework in Frameworks */, 171 | D95F88EE17E8C259000ADE35 /* libFFmpegWrapper.a in Frameworks */, 172 | D95F88E917E8C259000ADE35 /* Foundation.framework in Frameworks */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXFrameworksBuildPhase section */ 177 | 178 | /* Begin PBXGroup section */ 179 | D95F88CD17E8C259000ADE35 = { 180 | isa = PBXGroup; 181 | children = ( 182 | D9CF4BA517E8CA4600E7EE87 /* Submodules */, 183 | D95F88DB17E8C259000ADE35 /* FFmpegWrapper */, 184 | D95F88EF17E8C259000ADE35 /* FFmpegWrapperTests */, 185 | D95F88D817E8C259000ADE35 /* Frameworks */, 186 | D95F88D717E8C259000ADE35 /* Products */, 187 | ); 188 | sourceTree = ""; 189 | }; 190 | D95F88D717E8C259000ADE35 /* Products */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | D95F88D617E8C259000ADE35 /* libFFmpegWrapper.a */, 194 | D95F88E617E8C259000ADE35 /* FFmpegWrapperTests.xctest */, 195 | ); 196 | name = Products; 197 | sourceTree = ""; 198 | }; 199 | D95F88D817E8C259000ADE35 /* Frameworks */ = { 200 | isa = PBXGroup; 201 | children = ( 202 | D95F88D917E8C259000ADE35 /* Foundation.framework */, 203 | D95F88E717E8C259000ADE35 /* XCTest.framework */, 204 | D95F88EA17E8C259000ADE35 /* UIKit.framework */, 205 | ); 206 | name = Frameworks; 207 | sourceTree = ""; 208 | }; 209 | D95F88DB17E8C259000ADE35 /* FFmpegWrapper */ = { 210 | isa = PBXGroup; 211 | children = ( 212 | D95F88DE17E8C259000ADE35 /* FFmpegWrapper.h */, 213 | D95F88E017E8C259000ADE35 /* FFmpegWrapper.m */, 214 | D95F88DC17E8C259000ADE35 /* Supporting Files */, 215 | ); 216 | path = FFmpegWrapper; 217 | sourceTree = ""; 218 | }; 219 | D95F88DC17E8C259000ADE35 /* Supporting Files */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | D95F88DD17E8C259000ADE35 /* FFmpegWrapper-Prefix.pch */, 223 | ); 224 | name = "Supporting Files"; 225 | sourceTree = ""; 226 | }; 227 | D95F88EF17E8C259000ADE35 /* FFmpegWrapperTests */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | D95F88F517E8C259000ADE35 /* FFmpegWrapperTests.m */, 231 | D95F88F017E8C259000ADE35 /* Supporting Files */, 232 | ); 233 | path = FFmpegWrapperTests; 234 | sourceTree = ""; 235 | }; 236 | D95F88F017E8C259000ADE35 /* Supporting Files */ = { 237 | isa = PBXGroup; 238 | children = ( 239 | D95F88F117E8C259000ADE35 /* FFmpegWrapperTests-Info.plist */, 240 | D95F88F217E8C259000ADE35 /* InfoPlist.strings */, 241 | ); 242 | name = "Supporting Files"; 243 | sourceTree = ""; 244 | }; 245 | D9CF4B4017E8CA1A00E7EE87 /* include */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | D9CF4B4117E8CA1A00E7EE87 /* libavcodec */, 249 | D9CF4B4B17E8CA1A00E7EE87 /* libavdevice */, 250 | D9CF4B4E17E8CA1A00E7EE87 /* libavfilter */, 251 | D9CF4B5617E8CA1A00E7EE87 /* libavformat */, 252 | D9CF4B5A17E8CA1A00E7EE87 /* libavutil */, 253 | D9CF4B8F17E8CA1A00E7EE87 /* libswresample */, 254 | D9CF4B9217E8CA1A00E7EE87 /* libswscale */, 255 | ); 256 | name = include; 257 | path = "Submodules/FFmpeg-iOS/dependencies/include"; 258 | sourceTree = ""; 259 | }; 260 | D9CF4B4117E8CA1A00E7EE87 /* libavcodec */ = { 261 | isa = PBXGroup; 262 | children = ( 263 | D9CF4B4217E8CA1A00E7EE87 /* avcodec.h */, 264 | D9CF4B4317E8CA1A00E7EE87 /* avfft.h */, 265 | D9CF4B4417E8CA1A00E7EE87 /* dxva2.h */, 266 | D9CF4B4517E8CA1A00E7EE87 /* old_codec_ids.h */, 267 | D9CF4B4617E8CA1A00E7EE87 /* vaapi.h */, 268 | D9CF4B4717E8CA1A00E7EE87 /* vda.h */, 269 | D9CF4B4817E8CA1A00E7EE87 /* vdpau.h */, 270 | D9CF4B4917E8CA1A00E7EE87 /* version.h */, 271 | D9CF4B4A17E8CA1A00E7EE87 /* xvmc.h */, 272 | ); 273 | path = libavcodec; 274 | sourceTree = ""; 275 | }; 276 | D9CF4B4B17E8CA1A00E7EE87 /* libavdevice */ = { 277 | isa = PBXGroup; 278 | children = ( 279 | D9CF4B4C17E8CA1A00E7EE87 /* avdevice.h */, 280 | D9CF4B4D17E8CA1A00E7EE87 /* version.h */, 281 | ); 282 | path = libavdevice; 283 | sourceTree = ""; 284 | }; 285 | D9CF4B4E17E8CA1A00E7EE87 /* libavfilter */ = { 286 | isa = PBXGroup; 287 | children = ( 288 | D9CF4B4F17E8CA1A00E7EE87 /* asrc_abuffer.h */, 289 | D9CF4B5017E8CA1A00E7EE87 /* avcodec.h */, 290 | D9CF4B5117E8CA1A00E7EE87 /* avfilter.h */, 291 | D9CF4B5217E8CA1A00E7EE87 /* avfiltergraph.h */, 292 | D9CF4B5317E8CA1A00E7EE87 /* buffersink.h */, 293 | D9CF4B5417E8CA1A00E7EE87 /* buffersrc.h */, 294 | D9CF4B5517E8CA1A00E7EE87 /* version.h */, 295 | ); 296 | path = libavfilter; 297 | sourceTree = ""; 298 | }; 299 | D9CF4B5617E8CA1A00E7EE87 /* libavformat */ = { 300 | isa = PBXGroup; 301 | children = ( 302 | D9CF4B5717E8CA1A00E7EE87 /* avformat.h */, 303 | D9CF4B5817E8CA1A00E7EE87 /* avio.h */, 304 | D9CF4B5917E8CA1A00E7EE87 /* version.h */, 305 | ); 306 | path = libavformat; 307 | sourceTree = ""; 308 | }; 309 | D9CF4B5A17E8CA1A00E7EE87 /* libavutil */ = { 310 | isa = PBXGroup; 311 | children = ( 312 | D9CF4B5B17E8CA1A00E7EE87 /* adler32.h */, 313 | D9CF4B5C17E8CA1A00E7EE87 /* aes.h */, 314 | D9CF4B5D17E8CA1A00E7EE87 /* attributes.h */, 315 | D9CF4B5E17E8CA1A00E7EE87 /* audio_fifo.h */, 316 | D9CF4B5F17E8CA1A00E7EE87 /* audioconvert.h */, 317 | D9CF4B6017E8CA1A00E7EE87 /* avassert.h */, 318 | D9CF4B6117E8CA1A00E7EE87 /* avconfig.h */, 319 | D9CF4B6217E8CA1A00E7EE87 /* avstring.h */, 320 | D9CF4B6317E8CA1A00E7EE87 /* avutil.h */, 321 | D9CF4B6417E8CA1A00E7EE87 /* base64.h */, 322 | D9CF4B6517E8CA1A00E7EE87 /* blowfish.h */, 323 | D9CF4B6617E8CA1A00E7EE87 /* bprint.h */, 324 | D9CF4B6717E8CA1A00E7EE87 /* bswap.h */, 325 | D9CF4B6817E8CA1A00E7EE87 /* buffer.h */, 326 | D9CF4B6917E8CA1A00E7EE87 /* channel_layout.h */, 327 | D9CF4B6A17E8CA1A00E7EE87 /* common.h */, 328 | D9CF4B6B17E8CA1A00E7EE87 /* cpu.h */, 329 | D9CF4B6C17E8CA1A00E7EE87 /* crc.h */, 330 | D9CF4B6D17E8CA1A00E7EE87 /* dict.h */, 331 | D9CF4B6E17E8CA1A00E7EE87 /* error.h */, 332 | D9CF4B6F17E8CA1A00E7EE87 /* eval.h */, 333 | D9CF4B7017E8CA1A00E7EE87 /* fifo.h */, 334 | D9CF4B7117E8CA1A00E7EE87 /* file.h */, 335 | D9CF4B7217E8CA1A00E7EE87 /* frame.h */, 336 | D9CF4B7317E8CA1A00E7EE87 /* hmac.h */, 337 | D9CF4B7417E8CA1A00E7EE87 /* imgutils.h */, 338 | D9CF4B7517E8CA1A00E7EE87 /* intfloat.h */, 339 | D9CF4B7617E8CA1A00E7EE87 /* intfloat_readwrite.h */, 340 | D9CF4B7717E8CA1A00E7EE87 /* intreadwrite.h */, 341 | D9CF4B7817E8CA1A00E7EE87 /* lfg.h */, 342 | D9CF4B7917E8CA1A00E7EE87 /* log.h */, 343 | D9CF4B7A17E8CA1A00E7EE87 /* lzo.h */, 344 | D9CF4B7B17E8CA1A00E7EE87 /* mathematics.h */, 345 | D9CF4B7C17E8CA1A00E7EE87 /* md5.h */, 346 | D9CF4B7D17E8CA1A00E7EE87 /* mem.h */, 347 | D9CF4B7E17E8CA1A00E7EE87 /* murmur3.h */, 348 | D9CF4B7F17E8CA1A00E7EE87 /* old_pix_fmts.h */, 349 | D9CF4B8017E8CA1A00E7EE87 /* opt.h */, 350 | D9CF4B8117E8CA1A00E7EE87 /* parseutils.h */, 351 | D9CF4B8217E8CA1A00E7EE87 /* pixdesc.h */, 352 | D9CF4B8317E8CA1A00E7EE87 /* pixfmt.h */, 353 | D9CF4B8417E8CA1A00E7EE87 /* random_seed.h */, 354 | D9CF4B8517E8CA1A00E7EE87 /* rational.h */, 355 | D9CF4B8617E8CA1A00E7EE87 /* ripemd.h */, 356 | D9CF4B8717E8CA1A00E7EE87 /* samplefmt.h */, 357 | D9CF4B8817E8CA1A00E7EE87 /* sha.h */, 358 | D9CF4B8917E8CA1A00E7EE87 /* sha512.h */, 359 | D9CF4B8A17E8CA1A00E7EE87 /* time.h */, 360 | D9CF4B8B17E8CA1A00E7EE87 /* timecode.h */, 361 | D9CF4B8C17E8CA1A00E7EE87 /* timestamp.h */, 362 | D9CF4B8D17E8CA1A00E7EE87 /* version.h */, 363 | D9CF4B8E17E8CA1A00E7EE87 /* xtea.h */, 364 | ); 365 | path = libavutil; 366 | sourceTree = ""; 367 | }; 368 | D9CF4B8F17E8CA1A00E7EE87 /* libswresample */ = { 369 | isa = PBXGroup; 370 | children = ( 371 | D9CF4B9017E8CA1A00E7EE87 /* swresample.h */, 372 | D9CF4B9117E8CA1A00E7EE87 /* version.h */, 373 | ); 374 | path = libswresample; 375 | sourceTree = ""; 376 | }; 377 | D9CF4B9217E8CA1A00E7EE87 /* libswscale */ = { 378 | isa = PBXGroup; 379 | children = ( 380 | D9CF4B9317E8CA1A00E7EE87 /* swscale.h */, 381 | D9CF4B9417E8CA1A00E7EE87 /* version.h */, 382 | ); 383 | path = libswscale; 384 | sourceTree = ""; 385 | }; 386 | D9CF4B9517E8CA1A00E7EE87 /* lib */ = { 387 | isa = PBXGroup; 388 | children = ( 389 | D9CF4B9617E8CA1A00E7EE87 /* libavcodec.a */, 390 | D9CF4B9717E8CA1A00E7EE87 /* libavdevice.a */, 391 | D9CF4B9817E8CA1A00E7EE87 /* libavfilter.a */, 392 | D9CF4B9917E8CA1A00E7EE87 /* libavformat.a */, 393 | D9CF4B9A17E8CA1A00E7EE87 /* libavutil.a */, 394 | D9CF4B9B17E8CA1A00E7EE87 /* libswresample.a */, 395 | D9CF4B9C17E8CA1A00E7EE87 /* libswscale.a */, 396 | ); 397 | name = lib; 398 | path = "Submodules/FFmpeg-iOS/dependencies/lib"; 399 | sourceTree = ""; 400 | }; 401 | D9CF4BA417E8CA3100E7EE87 /* FFmpeg-iOS */ = { 402 | isa = PBXGroup; 403 | children = ( 404 | D9CF4B4017E8CA1A00E7EE87 /* include */, 405 | D9CF4B9517E8CA1A00E7EE87 /* lib */, 406 | ); 407 | name = "FFmpeg-iOS"; 408 | sourceTree = ""; 409 | }; 410 | D9CF4BA517E8CA4600E7EE87 /* Submodules */ = { 411 | isa = PBXGroup; 412 | children = ( 413 | D9CF4BA417E8CA3100E7EE87 /* FFmpeg-iOS */, 414 | ); 415 | name = Submodules; 416 | sourceTree = ""; 417 | }; 418 | /* End PBXGroup section */ 419 | 420 | /* Begin PBXNativeTarget section */ 421 | D95F88D517E8C259000ADE35 /* FFmpegWrapper */ = { 422 | isa = PBXNativeTarget; 423 | buildConfigurationList = D95F88F917E8C259000ADE35 /* Build configuration list for PBXNativeTarget "FFmpegWrapper" */; 424 | buildPhases = ( 425 | D95F88D217E8C259000ADE35 /* Sources */, 426 | D95F88D317E8C259000ADE35 /* Frameworks */, 427 | D95F88D417E8C259000ADE35 /* CopyFiles */, 428 | ); 429 | buildRules = ( 430 | ); 431 | dependencies = ( 432 | ); 433 | name = FFmpegWrapper; 434 | productName = FFmpegWrapper; 435 | productReference = D95F88D617E8C259000ADE35 /* libFFmpegWrapper.a */; 436 | productType = "com.apple.product-type.library.static"; 437 | }; 438 | D95F88E517E8C259000ADE35 /* FFmpegWrapperTests */ = { 439 | isa = PBXNativeTarget; 440 | buildConfigurationList = D95F88FC17E8C259000ADE35 /* Build configuration list for PBXNativeTarget "FFmpegWrapperTests" */; 441 | buildPhases = ( 442 | D95F88E217E8C259000ADE35 /* Sources */, 443 | D95F88E317E8C259000ADE35 /* Frameworks */, 444 | D95F88E417E8C259000ADE35 /* Resources */, 445 | ); 446 | buildRules = ( 447 | ); 448 | dependencies = ( 449 | D95F88ED17E8C259000ADE35 /* PBXTargetDependency */, 450 | ); 451 | name = FFmpegWrapperTests; 452 | productName = FFmpegWrapperTests; 453 | productReference = D95F88E617E8C259000ADE35 /* FFmpegWrapperTests.xctest */; 454 | productType = "com.apple.product-type.bundle.unit-test"; 455 | }; 456 | /* End PBXNativeTarget section */ 457 | 458 | /* Begin PBXProject section */ 459 | D95F88CE17E8C259000ADE35 /* Project object */ = { 460 | isa = PBXProject; 461 | attributes = { 462 | LastUpgradeCheck = 0500; 463 | ORGANIZATIONNAME = "OpenWatch, Inc."; 464 | }; 465 | buildConfigurationList = D95F88D117E8C259000ADE35 /* Build configuration list for PBXProject "FFmpegWrapper" */; 466 | compatibilityVersion = "Xcode 3.2"; 467 | developmentRegion = English; 468 | hasScannedForEncodings = 0; 469 | knownRegions = ( 470 | en, 471 | ); 472 | mainGroup = D95F88CD17E8C259000ADE35; 473 | productRefGroup = D95F88D717E8C259000ADE35 /* Products */; 474 | projectDirPath = ""; 475 | projectRoot = ""; 476 | targets = ( 477 | D95F88D517E8C259000ADE35 /* FFmpegWrapper */, 478 | D95F88E517E8C259000ADE35 /* FFmpegWrapperTests */, 479 | ); 480 | }; 481 | /* End PBXProject section */ 482 | 483 | /* Begin PBXResourcesBuildPhase section */ 484 | D95F88E417E8C259000ADE35 /* Resources */ = { 485 | isa = PBXResourcesBuildPhase; 486 | buildActionMask = 2147483647; 487 | files = ( 488 | D95F88F417E8C259000ADE35 /* InfoPlist.strings in Resources */, 489 | ); 490 | runOnlyForDeploymentPostprocessing = 0; 491 | }; 492 | /* End PBXResourcesBuildPhase section */ 493 | 494 | /* Begin PBXSourcesBuildPhase section */ 495 | D95F88D217E8C259000ADE35 /* Sources */ = { 496 | isa = PBXSourcesBuildPhase; 497 | buildActionMask = 2147483647; 498 | files = ( 499 | D95F88E117E8C259000ADE35 /* FFmpegWrapper.m in Sources */, 500 | ); 501 | runOnlyForDeploymentPostprocessing = 0; 502 | }; 503 | D95F88E217E8C259000ADE35 /* Sources */ = { 504 | isa = PBXSourcesBuildPhase; 505 | buildActionMask = 2147483647; 506 | files = ( 507 | D95F88F617E8C259000ADE35 /* FFmpegWrapperTests.m in Sources */, 508 | ); 509 | runOnlyForDeploymentPostprocessing = 0; 510 | }; 511 | /* End PBXSourcesBuildPhase section */ 512 | 513 | /* Begin PBXTargetDependency section */ 514 | D95F88ED17E8C259000ADE35 /* PBXTargetDependency */ = { 515 | isa = PBXTargetDependency; 516 | target = D95F88D517E8C259000ADE35 /* FFmpegWrapper */; 517 | targetProxy = D95F88EC17E8C259000ADE35 /* PBXContainerItemProxy */; 518 | }; 519 | /* End PBXTargetDependency section */ 520 | 521 | /* Begin PBXVariantGroup section */ 522 | D95F88F217E8C259000ADE35 /* InfoPlist.strings */ = { 523 | isa = PBXVariantGroup; 524 | children = ( 525 | D95F88F317E8C259000ADE35 /* en */, 526 | ); 527 | name = InfoPlist.strings; 528 | sourceTree = ""; 529 | }; 530 | /* End PBXVariantGroup section */ 531 | 532 | /* Begin XCBuildConfiguration section */ 533 | D95F88F717E8C259000ADE35 /* Debug */ = { 534 | isa = XCBuildConfiguration; 535 | buildSettings = { 536 | ALWAYS_SEARCH_USER_PATHS = NO; 537 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 538 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 539 | CLANG_CXX_LIBRARY = "libc++"; 540 | CLANG_ENABLE_MODULES = YES; 541 | CLANG_ENABLE_OBJC_ARC = YES; 542 | CLANG_WARN_BOOL_CONVERSION = YES; 543 | CLANG_WARN_CONSTANT_CONVERSION = YES; 544 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 545 | CLANG_WARN_EMPTY_BODY = YES; 546 | CLANG_WARN_ENUM_CONVERSION = YES; 547 | CLANG_WARN_INT_CONVERSION = YES; 548 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 549 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 550 | COPY_PHASE_STRIP = NO; 551 | GCC_C_LANGUAGE_STANDARD = gnu99; 552 | GCC_DYNAMIC_NO_PIC = NO; 553 | GCC_OPTIMIZATION_LEVEL = 0; 554 | GCC_PREPROCESSOR_DEFINITIONS = ( 555 | "DEBUG=1", 556 | "$(inherited)", 557 | ); 558 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 559 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 560 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 561 | GCC_WARN_UNDECLARED_SELECTOR = YES; 562 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 563 | GCC_WARN_UNUSED_FUNCTION = YES; 564 | GCC_WARN_UNUSED_VARIABLE = YES; 565 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 566 | ONLY_ACTIVE_ARCH = YES; 567 | SDKROOT = iphoneos; 568 | }; 569 | name = Debug; 570 | }; 571 | D95F88F817E8C259000ADE35 /* Release */ = { 572 | isa = XCBuildConfiguration; 573 | buildSettings = { 574 | ALWAYS_SEARCH_USER_PATHS = NO; 575 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 576 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 577 | CLANG_CXX_LIBRARY = "libc++"; 578 | CLANG_ENABLE_MODULES = YES; 579 | CLANG_ENABLE_OBJC_ARC = YES; 580 | CLANG_WARN_BOOL_CONVERSION = YES; 581 | CLANG_WARN_CONSTANT_CONVERSION = YES; 582 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 583 | CLANG_WARN_EMPTY_BODY = YES; 584 | CLANG_WARN_ENUM_CONVERSION = YES; 585 | CLANG_WARN_INT_CONVERSION = YES; 586 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 587 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 588 | COPY_PHASE_STRIP = YES; 589 | ENABLE_NS_ASSERTIONS = NO; 590 | GCC_C_LANGUAGE_STANDARD = gnu99; 591 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 592 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 593 | GCC_WARN_UNDECLARED_SELECTOR = YES; 594 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 595 | GCC_WARN_UNUSED_FUNCTION = YES; 596 | GCC_WARN_UNUSED_VARIABLE = YES; 597 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 598 | SDKROOT = iphoneos; 599 | VALIDATE_PRODUCT = YES; 600 | }; 601 | name = Release; 602 | }; 603 | D95F88FA17E8C259000ADE35 /* Debug */ = { 604 | isa = XCBuildConfiguration; 605 | buildSettings = { 606 | DSTROOT = /tmp/FFmpegWrapper.dst; 607 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 608 | GCC_PREFIX_HEADER = "FFmpegWrapper/FFmpegWrapper-Prefix.pch"; 609 | HEADER_SEARCH_PATHS = ( 610 | "$(inherited)", 611 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 612 | "$(SRCROOT)/Submodules/FFmpeg-iOS/dependencies/include", 613 | ); 614 | LIBRARY_SEARCH_PATHS = ( 615 | "$(inherited)", 616 | "/Users/chrisbal/FFmpegWrapper/Submodules/FFmpeg-iOS/dependencies/lib", 617 | ); 618 | OTHER_LDFLAGS = "-ObjC"; 619 | PRODUCT_NAME = "$(TARGET_NAME)"; 620 | SKIP_INSTALL = YES; 621 | }; 622 | name = Debug; 623 | }; 624 | D95F88FB17E8C259000ADE35 /* Release */ = { 625 | isa = XCBuildConfiguration; 626 | buildSettings = { 627 | DSTROOT = /tmp/FFmpegWrapper.dst; 628 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 629 | GCC_PREFIX_HEADER = "FFmpegWrapper/FFmpegWrapper-Prefix.pch"; 630 | HEADER_SEARCH_PATHS = ( 631 | "$(inherited)", 632 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 633 | "$(SRCROOT)/Submodules/FFmpeg-iOS/dependencies/include", 634 | ); 635 | LIBRARY_SEARCH_PATHS = ( 636 | "$(inherited)", 637 | "/Users/chrisbal/FFmpegWrapper/Submodules/FFmpeg-iOS/dependencies/lib", 638 | ); 639 | OTHER_LDFLAGS = "-ObjC"; 640 | PRODUCT_NAME = "$(TARGET_NAME)"; 641 | SKIP_INSTALL = YES; 642 | }; 643 | name = Release; 644 | }; 645 | D95F88FD17E8C259000ADE35 /* Debug */ = { 646 | isa = XCBuildConfiguration; 647 | buildSettings = { 648 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 649 | FRAMEWORK_SEARCH_PATHS = ( 650 | "$(SDKROOT)/Developer/Library/Frameworks", 651 | "$(inherited)", 652 | "$(DEVELOPER_FRAMEWORKS_DIR)", 653 | ); 654 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 655 | GCC_PREFIX_HEADER = "FFmpegWrapper/FFmpegWrapper-Prefix.pch"; 656 | GCC_PREPROCESSOR_DEFINITIONS = ( 657 | "DEBUG=1", 658 | "$(inherited)", 659 | ); 660 | INFOPLIST_FILE = "FFmpegWrapperTests/FFmpegWrapperTests-Info.plist"; 661 | PRODUCT_NAME = "$(TARGET_NAME)"; 662 | WRAPPER_EXTENSION = xctest; 663 | }; 664 | name = Debug; 665 | }; 666 | D95F88FE17E8C259000ADE35 /* Release */ = { 667 | isa = XCBuildConfiguration; 668 | buildSettings = { 669 | ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; 670 | FRAMEWORK_SEARCH_PATHS = ( 671 | "$(SDKROOT)/Developer/Library/Frameworks", 672 | "$(inherited)", 673 | "$(DEVELOPER_FRAMEWORKS_DIR)", 674 | ); 675 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 676 | GCC_PREFIX_HEADER = "FFmpegWrapper/FFmpegWrapper-Prefix.pch"; 677 | INFOPLIST_FILE = "FFmpegWrapperTests/FFmpegWrapperTests-Info.plist"; 678 | PRODUCT_NAME = "$(TARGET_NAME)"; 679 | WRAPPER_EXTENSION = xctest; 680 | }; 681 | name = Release; 682 | }; 683 | /* End XCBuildConfiguration section */ 684 | 685 | /* Begin XCConfigurationList section */ 686 | D95F88D117E8C259000ADE35 /* Build configuration list for PBXProject "FFmpegWrapper" */ = { 687 | isa = XCConfigurationList; 688 | buildConfigurations = ( 689 | D95F88F717E8C259000ADE35 /* Debug */, 690 | D95F88F817E8C259000ADE35 /* Release */, 691 | ); 692 | defaultConfigurationIsVisible = 0; 693 | defaultConfigurationName = Release; 694 | }; 695 | D95F88F917E8C259000ADE35 /* Build configuration list for PBXNativeTarget "FFmpegWrapper" */ = { 696 | isa = XCConfigurationList; 697 | buildConfigurations = ( 698 | D95F88FA17E8C259000ADE35 /* Debug */, 699 | D95F88FB17E8C259000ADE35 /* Release */, 700 | ); 701 | defaultConfigurationIsVisible = 0; 702 | defaultConfigurationName = Release; 703 | }; 704 | D95F88FC17E8C259000ADE35 /* Build configuration list for PBXNativeTarget "FFmpegWrapperTests" */ = { 705 | isa = XCConfigurationList; 706 | buildConfigurations = ( 707 | D95F88FD17E8C259000ADE35 /* Debug */, 708 | D95F88FE17E8C259000ADE35 /* Release */, 709 | ); 710 | defaultConfigurationIsVisible = 0; 711 | defaultConfigurationName = Release; 712 | }; 713 | /* End XCConfigurationList section */ 714 | }; 715 | rootObject = D95F88CE17E8C259000ADE35 /* Project object */; 716 | } 717 | -------------------------------------------------------------------------------- /FFmpegWrapper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FFmpegWrapper.xcodeproj/xcuserdata/chrisbal.xcuserdatad/xcschemes/FFmpegWrapper.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 52 | 53 | 54 | 55 | 61 | 62 | 64 | 65 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /FFmpegWrapper.xcodeproj/xcuserdata/chrisbal.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FFmpegWrapper.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D95F88D517E8C259000ADE35 16 | 17 | primary 18 | 19 | 20 | D95F88E517E8C259000ADE35 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFBitstreamFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFBitstreamFilter.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "libavcodec/avcodec.h" 12 | 13 | @interface FFBitstreamFilter : NSObject 14 | 15 | @property (nonatomic) AVBitStreamFilterContext *bitstreamFilterContext; 16 | 17 | - (id) initWithFilterName:(NSString*)filterName; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFBitstreamFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFBitstreamFilter.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFBitstreamFilter.h" 10 | 11 | @implementation FFBitstreamFilter 12 | @synthesize bitstreamFilterContext; 13 | 14 | - (void) dealloc { 15 | av_bitstream_filter_close(bitstreamFilterContext); 16 | } 17 | 18 | - (id) initWithFilterName:(NSString *)filterName { 19 | if (self = [super init]) { 20 | self.bitstreamFilterContext = av_bitstream_filter_init([filterName UTF8String]); 21 | } 22 | return self; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFFile.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "libavformat/avformat.h" 11 | 12 | @interface FFFile : NSObject 13 | @property (nonatomic, strong) NSString *path; 14 | @property (nonatomic, strong) NSDictionary *options; 15 | @property (nonatomic) AVFormatContext *formatContext; 16 | @property (nonatomic) NSArray *streams; 17 | 18 | - (id) initWithPath:(NSString*)path options:(NSDictionary*)options; 19 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFFile.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFFile.h" 10 | 11 | @implementation FFFile 12 | @synthesize formatContext, streams; 13 | 14 | - (id) initWithPath:(NSString *)newPath options:(NSDictionary *)newOptions { 15 | if (self = [super init]) { 16 | self.path = newPath; 17 | self.options = newOptions; 18 | } 19 | return self; 20 | } 21 | 22 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFInputFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFInputFile.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFFile.h" 10 | 11 | @interface FFInputFile : FFFile 12 | @property (nonatomic) BOOL endOfFileReached; 13 | @property (nonatomic) int64_t timestampOffset; 14 | @property (nonatomic) int64_t lastTimestamp; 15 | 16 | // True if more, false if EOF reached 17 | - (BOOL) readFrameIntoPacket:(AVPacket*)packet error:(NSError**)error; 18 | 19 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFInputFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFInputFile.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFInputFile.h" 10 | #import "FFInputStream.h" 11 | #import "FFUtilities.h" 12 | 13 | NSString const *kFFmpegInputFormatKey = @"kFFmpegInputFormatKey"; 14 | 15 | @implementation FFInputFile 16 | @synthesize endOfFileReached, timestampOffset, lastTimestamp, formatContext; 17 | 18 | - (void) dealloc { 19 | avformat_close_input(&formatContext); 20 | } 21 | 22 | - (AVFormatContext*) formatContextForInputPath:(NSString*)inputPath options:(NSDictionary*)options { 23 | // You can override the detected input format 24 | AVFormatContext *inputFormatContext = NULL; 25 | AVInputFormat *inputFormat = NULL; 26 | AVDictionary *inputOptions = NULL; 27 | 28 | NSString *inputFormatString = [options objectForKey:kFFmpegInputFormatKey]; 29 | if (inputFormatString) { 30 | inputFormat = av_find_input_format([inputFormatString UTF8String]); 31 | } 32 | 33 | // It's possible to send more options to the parser 34 | // av_dict_set(&inputOptions, "video_size", "640x480", 0); 35 | // av_dict_set(&inputOptions, "pixel_format", "rgb24", 0); 36 | // av_dict_free(&inputOptions); // Don't forget to free 37 | 38 | int openInputValue = avformat_open_input(&inputFormatContext, [inputPath UTF8String], inputFormat, &inputOptions); 39 | if (openInputValue != 0) { 40 | avformat_close_input(&inputFormatContext); 41 | return nil; 42 | } 43 | 44 | int streamInfoValue = avformat_find_stream_info(inputFormatContext, NULL); 45 | if (streamInfoValue < 0) { 46 | avformat_close_input(&inputFormatContext); 47 | return nil; 48 | } 49 | return inputFormatContext; 50 | } 51 | 52 | - (void) populateStreams { 53 | NSUInteger inputStreamCount = formatContext->nb_streams; 54 | NSMutableArray *inputStreams = [NSMutableArray arrayWithCapacity:inputStreamCount]; 55 | for (int i = 0; i < inputStreamCount; i++) { 56 | AVStream *inputStream = formatContext->streams[i]; 57 | FFInputStream *ffInputStream = [[FFInputStream alloc] initWithInputFile:self stream:inputStream]; 58 | [inputStreams addObject:ffInputStream]; 59 | } 60 | self.streams = inputStreams; 61 | } 62 | 63 | - (id) initWithPath:(NSString *)path options:(NSDictionary *)options { 64 | if (self = [super initWithPath:path options:options]) { 65 | self.formatContext = [self formatContextForInputPath:path options:options]; 66 | [self populateStreams]; 67 | } 68 | return self; 69 | } 70 | 71 | - (BOOL) readFrameIntoPacket:(AVPacket*)packet error:(NSError *__autoreleasing *)error { 72 | BOOL continueReading = YES; 73 | int frameReadValue = av_read_frame(self.formatContext, packet); 74 | if (frameReadValue != 0) { 75 | continueReading = NO; 76 | if (frameReadValue != AVERROR_EOF) { 77 | if (error != NULL) { 78 | *error = [FFUtilities errorForAVError:frameReadValue]; 79 | } 80 | } 81 | av_free_packet(packet); 82 | } 83 | return continueReading; 84 | } 85 | 86 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFInputStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFInputStream.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFStream.h" 10 | 11 | @class FFInputFile; 12 | 13 | @interface FFInputStream : FFStream 14 | /* predicted dts of the next packet read for this stream or (when there are 15 | * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ 16 | @property (nonatomic) int64_t nextDTS; 17 | @property (nonatomic) int64_t DTS; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) 18 | 19 | @property (nonatomic) int64_t nextPTS; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) 20 | @property (nonatomic) int64_t PTS; ///< current pts of the decoded frame (in AV_TIME_BASE units) 21 | @property (nonatomic) int64_t filterInRescaleDeltaLast; 22 | 23 | @property (nonatomic) BOOL sawFirstTS; 24 | @property (nonatomic) BOOL wrapCorrectionDone; 25 | @property (nonatomic) double timestampScale; 26 | 27 | - (id) initWithInputFile:(FFInputFile*)newInputFile stream:(AVStream*)newStream; 28 | @end 29 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFInputStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFInputStream.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFInputStream.h" 10 | #import "FFInputFile.h" 11 | 12 | #import "libavutil/timestamp.h" 13 | 14 | @implementation FFInputStream 15 | @synthesize nextDTS, DTS, nextPTS, PTS; 16 | 17 | - (id) initWithInputFile:(FFInputFile*)newInputFile stream:(AVStream*)newStream { 18 | if (self = [super initWithFile:newInputFile]) { 19 | self.nextPTS = AV_NOPTS_VALUE; 20 | self.PTS = AV_NOPTS_VALUE; 21 | self.nextDTS = AV_NOPTS_VALUE; 22 | self.DTS = AV_NOPTS_VALUE; 23 | self.filterInRescaleDeltaLast = AV_NOPTS_VALUE; 24 | self.sawFirstTS = NO; 25 | self.wrapCorrectionDone = NO; 26 | self.stream = newStream; 27 | } 28 | return self; 29 | } 30 | 31 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFOutputFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFOutputFile.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFFile.h" 10 | 11 | #import "FFOutputStream.h" 12 | #import "libavcodec/avcodec.h" 13 | #import "FFBitstreamFilter.h" 14 | 15 | @interface FFOutputFile : FFFile 16 | @property (nonatomic) int64_t startTime; 17 | 18 | // No need to call this function directly, streams are automatically added when created 19 | - (void) addOutputStream:(FFOutputStream*)outputStream; 20 | 21 | 22 | - (void) addBitstreamFilter:(FFBitstreamFilter*)bitstreamFilter; 23 | - (void) removeBitstreamFilter:(FFBitstreamFilter*)bitstreamFilter; 24 | - (NSSet*) bitstreamFilters; 25 | 26 | 27 | // Must call this first 28 | - (BOOL) openFileForWritingWithError:(NSError**)error; 29 | // openFileForWritingWithError: must be called before calling this 30 | - (BOOL) writeHeaderWithError:(NSError**)error; 31 | // writeHeaderWithError: must be called before calling this 32 | - (BOOL) writePacket:(AVPacket*)packet error:(NSError**)error; 33 | // must call this when finished writing 34 | - (BOOL) writeTrailerWithError:(NSError**)error; 35 | 36 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFOutputFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFOutputFile.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFOutputFile.h" 10 | #import "FFUtilities.h" 11 | 12 | #import "libavutil/timestamp.h" 13 | 14 | NSString const *kFFmpegOutputFormatKey = @"kFFmpegOutputFormatKey"; 15 | 16 | @interface FFOutputFile() 17 | @property (nonatomic, strong) NSMutableArray *streams; 18 | @property (nonatomic, strong, readwrite) NSMutableSet *bitstreamFilters; 19 | @end 20 | 21 | @implementation FFOutputFile 22 | @synthesize startTime, formatContext, bitstreamFilters; 23 | 24 | - (void) addBitstreamFilter:(FFBitstreamFilter *)bitstreamFilter { 25 | [bitstreamFilters addObject:bitstreamFilter]; 26 | } 27 | 28 | - (void) removeBitstreamFilter:(FFBitstreamFilter *)bitstreamFilter { 29 | [bitstreamFilters removeObject:bitstreamFilter]; 30 | } 31 | 32 | - (NSSet*) bitstreamFilters { 33 | return self.bitstreamFilters; 34 | } 35 | 36 | - (void) dealloc { 37 | avformat_free_context(formatContext); 38 | } 39 | 40 | - (AVFormatContext*) formatContextForOutputPath:(NSString*)outputPath options:(NSDictionary*)options { 41 | AVFormatContext *outputFormatContext = NULL; 42 | NSString *outputFormatString = [options objectForKey:kFFmpegOutputFormatKey]; 43 | 44 | int openOutputValue = avformat_alloc_output_context2(&outputFormatContext, NULL, [outputFormatString UTF8String], [outputPath UTF8String]); 45 | if (openOutputValue < 0) { 46 | avformat_free_context(outputFormatContext); 47 | return nil; 48 | } 49 | return outputFormatContext; 50 | } 51 | 52 | - (void) addOutputStream:(FFOutputStream*)outputStream { 53 | [self.streams addObject:outputStream]; 54 | } 55 | 56 | - (id) initWithPath:(NSString *)path options:(NSDictionary *)options { 57 | if (self = [super initWithPath:path options:options]) { 58 | self.formatContext = [self formatContextForOutputPath:path options:options]; 59 | self.streams = [NSMutableArray array]; 60 | self.bitstreamFilters = [NSMutableSet set]; 61 | } 62 | return self; 63 | } 64 | 65 | - (BOOL) openFileForWritingWithError:(NSError *__autoreleasing *)error { 66 | /* open the output file, if needed */ 67 | if (!(formatContext->oformat->flags & AVFMT_NOFILE)) { 68 | int returnValue = avio_open(&formatContext->pb, [self.path UTF8String], AVIO_FLAG_WRITE); 69 | if (returnValue < 0) { 70 | if (error != NULL) { 71 | *error = [FFUtilities errorForAVError:returnValue]; 72 | } 73 | return NO; 74 | } 75 | } 76 | return YES; 77 | } 78 | 79 | - (BOOL) writeHeaderWithError:(NSError *__autoreleasing *)error { 80 | AVDictionary *options = NULL; 81 | 82 | // Write header for output file 83 | int writeHeaderValue = avformat_write_header(self.formatContext, &options); 84 | if (writeHeaderValue < 0) { 85 | if (error != NULL) { 86 | *error = [FFUtilities errorForAVError:writeHeaderValue]; 87 | } 88 | av_dict_free(&options); 89 | return NO; 90 | } 91 | av_dict_free(&options); 92 | return YES; 93 | } 94 | 95 | - (AVPacket) applyBitstreamFilter:(AVBitStreamFilterContext*)bitstreamFilterContext packet:(AVPacket*)packet outputCodecContext:(AVCodecContext*)outputCodecContext { 96 | AVPacket newPacket = *packet; 97 | int a = av_bitstream_filter_filter(bitstreamFilterContext, outputCodecContext, NULL, 98 | &newPacket.data, &newPacket.size, 99 | packet->data, packet->size, 100 | packet->flags & AV_PKT_FLAG_KEY); 101 | if(a == 0 && newPacket.data != packet->data && newPacket.destruct) { 102 | uint8_t *t = av_malloc(newPacket.size + FF_INPUT_BUFFER_PADDING_SIZE); //the new should be a subset of the old so cannot overflow 103 | if(t) { 104 | memcpy(t, newPacket.data, newPacket.size); 105 | memset(t + newPacket.size, 0, FF_INPUT_BUFFER_PADDING_SIZE); 106 | newPacket.data = t; 107 | newPacket.buf = NULL; 108 | a = 1; 109 | } else { 110 | a = AVERROR(ENOMEM); 111 | } 112 | 113 | } 114 | if (a > 0) { 115 | av_free_packet(packet); 116 | newPacket.buf = av_buffer_create(newPacket.data, newPacket.size, 117 | av_buffer_default_free, NULL, 0); 118 | if (!newPacket.buf) { 119 | NSLog(@"new packet buffer couldnt be allocated"); 120 | } 121 | 122 | } else if (a < 0) { 123 | NSLog(@"FFmpeg Error: Failed to open bitstream filter %s for stream %d with codec %s", bitstreamFilterContext->filter->name, packet->stream_index, 124 | outputCodecContext->codec ? outputCodecContext->codec->name : "copy"); 125 | } 126 | return newPacket; 127 | } 128 | 129 | - (BOOL) writePacket:(AVPacket *)packet error:(NSError *__autoreleasing *)error { 130 | if (!packet) { 131 | NSLog(@"NULL packet!"); 132 | return NO; 133 | } 134 | FFOutputStream *ffOutputStream = [self.streams objectAtIndex:packet->stream_index]; 135 | AVStream *outputStream = ffOutputStream.stream; 136 | 137 | AVCodecContext *outputCodecContext = outputStream->codec; 138 | 139 | //NSData *packetData = [NSData dataWithBytesNoCopy:packet->data length:packet->size freeWhenDone:NO]; 140 | //NSLog(@"Org: %@", packetData); 141 | if (outputCodecContext->codec_id == AV_CODEC_ID_H264) { 142 | for (FFBitstreamFilter *bsf in bitstreamFilters) { 143 | AVPacket newPacket = [self applyBitstreamFilter:bsf.bitstreamFilterContext packet:packet outputCodecContext:outputCodecContext]; 144 | av_free_packet(packet); 145 | packet = &newPacket; 146 | } 147 | //NSData *bsfData = [NSData dataWithBytesNoCopy:packet->data length:packet->size freeWhenDone:NO]; 148 | //NSLog(@"bsf: %@", bsfData); 149 | } 150 | 151 | ffOutputStream.lastMuxDTS = packet->dts; 152 | 153 | int writeFrameValue = av_interleaved_write_frame(self.formatContext, packet); 154 | if (writeFrameValue < 0) { 155 | if (error != NULL) { 156 | *error = [FFUtilities errorForAVError:writeFrameValue]; 157 | } 158 | return NO; 159 | } 160 | outputStream->codec->frame_number++; 161 | return YES; 162 | } 163 | 164 | - (BOOL) writeTrailerWithError:(NSError *__autoreleasing *)error { 165 | int writeTrailerValue = av_write_trailer(formatContext); 166 | if (writeTrailerValue < 0) { 167 | if (error != NULL) { 168 | *error = [FFUtilities errorForAVError:writeTrailerValue]; 169 | } 170 | return NO; 171 | } 172 | return YES; 173 | } 174 | 175 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFOutputStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFOutputStream.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFStream.h" 10 | 11 | @class FFOutputFile, FFFile; 12 | 13 | @interface FFOutputStream : FFStream 14 | 15 | @property (nonatomic) int64_t lastMuxDTS; 16 | @property (nonatomic) int frameNumber; 17 | @property (nonatomic, readonly) AVCodec *codec; 18 | 19 | - (id) initWithOutputFile:(FFOutputFile*)outputFile outputCodec:(NSString*)outputCodec; 20 | 21 | - (void) setupVideoContextWithWidth:(int)width height:(int)height; 22 | - (void) setupAudioContextWithSampleRate:(int)sampleRate; 23 | 24 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFOutputStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFOutputStream.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFOutputStream.h" 10 | #import "FFOutputFile.h" 11 | 12 | @implementation FFOutputStream 13 | @synthesize lastMuxDTS, frameNumber; 14 | 15 | - (id) initWithOutputFile:(FFOutputFile*)outputFile outputCodec:(NSString*)outputCodec { 16 | if (self = [super initWithFile:outputFile]) { 17 | self.lastMuxDTS = AV_NOPTS_VALUE; 18 | self.frameNumber = 0; 19 | 20 | AVCodec *codec = avcodec_find_encoder_by_name([outputCodec UTF8String]); 21 | if (!codec) { 22 | NSLog(@"codec not found: %@", outputCodec); 23 | } 24 | self.stream = avformat_new_stream(outputFile.formatContext, codec); 25 | [outputFile addOutputStream:self]; 26 | } 27 | return self; 28 | } 29 | 30 | - (void) setupVideoContextWithWidth:(int)width height:(int)height { 31 | AVCodecContext *c = self.stream->codec; 32 | avcodec_get_context_defaults3(c, NULL); 33 | c->codec_id = CODEC_ID_H264; 34 | c->codec_type = AVMEDIA_TYPE_VIDEO; 35 | c->width = width; 36 | c->height = height; 37 | c->bit_rate = 2000000; 38 | c->profile = FF_PROFILE_H264_BASELINE; 39 | c->time_base.den = 30; 40 | c->time_base.num = 1; 41 | c->pix_fmt = PIX_FMT_YUV420P; 42 | if (self.parentFile.formatContext->oformat->flags & AVFMT_GLOBALHEADER) 43 | c->flags |= CODEC_FLAG_GLOBAL_HEADER; 44 | } 45 | 46 | - (void) setupAudioContextWithSampleRate:(int)sampleRate { 47 | AVCodecContext *codecContext = self.stream->codec; 48 | int codecID = CODEC_ID_AAC; 49 | AVCodec *codec = avcodec_find_encoder(codecID); 50 | if (!codec) { 51 | NSLog(@"audio codec not found: %d", codecID); 52 | } 53 | /* find the audio encoder */ 54 | avcodec_get_context_defaults3(codecContext, codec); 55 | codecContext->codec_id = codecID; 56 | codecContext->codec_type = AVMEDIA_TYPE_AUDIO; 57 | 58 | //st->id = 1; 59 | codecContext->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL; // for native aac support 60 | /* put sample parameters */ 61 | //codecContext->sample_fmt = AV_SAMPLE_FMT_FLT; 62 | codecContext->sample_fmt = AV_SAMPLE_FMT_S16; 63 | codecContext->time_base.den = 44100; 64 | codecContext->time_base.num = 1; 65 | codecContext->channel_layout = AV_CH_LAYOUT_MONO; 66 | codecContext->profile = FF_PROFILE_AAC_LOW; 67 | codecContext->bit_rate = 64 * 1000; 68 | //c->bit_rate = bit_rate; 69 | codecContext->sample_rate = sampleRate; 70 | codecContext->channels = 1; 71 | //NSLog(@"addAudioStream sample_rate %d index %d", codecContext->sample_rate, self.stream->index); 72 | //LOGI("add_audio_stream parameters: sample_fmt: %d bit_rate: %d sample_rate: %d", codec_audio_sample_fmt, bit_rate, audio_sample_rate); 73 | // some formats want stream headers to be separate 74 | if (self.parentFile.formatContext->oformat->flags & AVFMT_GLOBALHEADER) 75 | codecContext->flags |= CODEC_FLAG_GLOBAL_HEADER; 76 | } 77 | 78 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFStream.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "libavformat/avformat.h" 11 | 12 | @class FFFile, FFInputStream, FFOutputStream; 13 | 14 | @interface FFStream : NSObject 15 | @property (nonatomic, weak) FFFile *parentFile; 16 | @property (nonatomic) AVStream *stream; 17 | 18 | - (id) initWithFile:(FFFile*)parentFile; 19 | - (NSString*) codecName; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFStream.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFStream.h" 10 | 11 | 12 | @implementation FFStream 13 | @synthesize stream, parentFile; 14 | - (id) initWithFile:(FFFile *)newParentFile { 15 | if (self = [super init]) { 16 | self.parentFile = newParentFile; 17 | } 18 | return self; 19 | } 20 | 21 | - (NSString*) codecName { 22 | if (!stream) { 23 | return nil; 24 | } 25 | AVCodecContext *inputCodecContext = stream->codec; 26 | const char *codec_name = avcodec_get_name(inputCodecContext->codec_id); 27 | return [NSString stringWithUTF8String:codec_name]; 28 | } 29 | 30 | @end -------------------------------------------------------------------------------- /FFmpegWrapper/FFUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFUtilities.h 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FFUtilities : NSObject 12 | 13 | + (NSError*) errorForAVError:(int)avErrorNumber; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFUtilities.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFUtilities.m 3 | // LiveStreamer 4 | // 5 | // Created by Christopher Ballinger on 10/1/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | 9 | #import "FFUtilities.h" 10 | #import "libavutil/error.h" 11 | 12 | static NSString * const kFFmpegErrorDomain = @"org.ffmpeg.FFmpeg"; 13 | static NSString * const kFFmpegErrorCode = @"kFFmpegErrorCode"; 14 | 15 | @implementation FFUtilities 16 | 17 | + (NSError*) errorForAVError:(int)errorNumber { 18 | NSString *errorString = [self stringForAVErrorNumber:errorNumber]; 19 | NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:1]; 20 | if (errorString) { 21 | [userInfo setObject:errorString forKey:NSLocalizedDescriptionKey]; 22 | } else { 23 | [userInfo setObject:@"Unknown FFmpeg Error" forKey:NSLocalizedDescriptionKey]; 24 | } 25 | [userInfo setObject:@(errorNumber) forKey:kFFmpegErrorCode]; 26 | return [NSError errorWithDomain:kFFmpegErrorDomain code:errorNumber userInfo:userInfo]; 27 | } 28 | 29 | + (NSString*) stringForAVErrorNumber:(int)errorNumber { 30 | NSString *errorString = nil; 31 | char *errorBuffer = malloc(sizeof(char) * AV_ERROR_MAX_STRING_SIZE); 32 | 33 | int value = av_strerror(errorNumber, errorBuffer, AV_ERROR_MAX_STRING_SIZE); 34 | if (value != 0) { 35 | return nil; 36 | } 37 | errorString = [NSString stringWithUTF8String:errorBuffer]; 38 | free(errorBuffer); 39 | return errorString; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFmpegWrapper-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFmpegWrapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // FFmpegWrapper.h 3 | // FFmpegWrapper 4 | // 5 | // Created by Christopher Ballinger on 9/14/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | // This file is part of FFmpegWrapper. 9 | // 10 | // FFmpegWrapper is free software; you can redistribute it and/or 11 | // modify it under the terms of the GNU Lesser General Public 12 | // License as published by the Free Software Foundation; either 13 | // version 2.1 of the License, or (at your option) any later version. 14 | // 15 | // FFmpegWrapper is distributed in the hope that it will be useful, 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | // Lesser General Public License for more details. 19 | // 20 | // You should have received a copy of the GNU Lesser General Public 21 | // License along with FFmpegWrapper; if not, write to the Free Software 22 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 | // 24 | 25 | #import 26 | 27 | ///------------------------------------------------- 28 | /// @name Callbacks 29 | ///------------------------------------------------- 30 | 31 | /** 32 | This callback is called when a job has finished or has failed. Defaults to the main queue. 33 | @param success Whether or not the job was successful. 34 | @param error If the job was not successful, there might be an error in here. 35 | */ 36 | typedef void(^FFmpegWrapperCompletionBlock)(BOOL success, NSError *error); 37 | 38 | /** 39 | This callback periodically reports on the progress of the job. Defaults to the main queue. 40 | @param bytesRead Number of bytes just read from the input file. 41 | @param totalBytesRead Total number of bytes read so far. 42 | @param totalBytesExpectedToRead Expected number of bytes to be read from input file. 43 | */ 44 | typedef void(^FFmpegWrapperProgressBlock)(NSUInteger bytesRead, uint64_t totalBytesRead, uint64_t totalBytesExpectedToRead); 45 | 46 | ///------------------------------------------------- 47 | /// @name Options 48 | ///------------------------------------------------- 49 | 50 | /** 51 | Optional. This controls the type of container for the input format. Accepts NSString values like @"mp4", @"avi", @"mpegts". For a full list of supported formats please consult `$ ffmpeg -formats`. 52 | */ 53 | extern NSString const *kFFmpegInputFormatKey; 54 | 55 | /** 56 | Required. This controls the type of container for the output format. Accepts NSString values like @"mp4", @"avi", @"mpegts". For a full list of supported formats please consult `$ ffmpeg -formats`. 57 | */ 58 | extern NSString const *kFFmpegOutputFormatKey; 59 | 60 | @interface FFmpegWrapper : NSObject 61 | 62 | /** 63 | Queue for all conversion jobs. (defaults to FIFO background queue) 64 | */ 65 | @property (nonatomic) dispatch_queue_t conversionQueue; 66 | 67 | /** 68 | Queue for all callbacks. (defaults to main queue) 69 | */ 70 | @property (nonatomic) dispatch_queue_t callbackQueue; 71 | 72 | ///------------------------------------------------- 73 | /// @name Conversion 74 | ///------------------------------------------------- 75 | 76 | /** 77 | Converts file at `inputPath` to a new file at `outputPath` using the parameters specified in the `options` dictionary. The two optional callbacks are for monitoring the progress and completion of a queued task and are always called on the main thread. All calls to this function are currently queued in a synchronous internal dispatch queue. 78 | 79 | @param inputPath Full path to the input file. 80 | @param outputPath Full path to output file. 81 | @param options Dictionary of key value pairs for settings. 82 | @param progressBlock Defaults to the main queue. 83 | @param completionblock Defaults to the main queue. 84 | */ 85 | - (void) convertInputPath:(NSString*)inputPath outputPath:(NSString*)outputPath options:(NSDictionary*)options progressBlock:(FFmpegWrapperProgressBlock)progressBlock completionBlock:(FFmpegWrapperCompletionBlock)completionBlock; 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /FFmpegWrapper/FFmpegWrapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // FFmpegWrapper.m 3 | // FFmpegWrapper 4 | // 5 | // Created by Christopher Ballinger on 9/14/13. 6 | // Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 7 | // 8 | // This file is part of FFmpegWrapper. 9 | // 10 | // FFmpegWrapper is free software; you can redistribute it and/or 11 | // modify it under the terms of the GNU Lesser General Public 12 | // License as published by the Free Software Foundation; either 13 | // version 2.1 of the License, or (at your option) any later version. 14 | // 15 | // FFmpegWrapper is distributed in the hope that it will be useful, 16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | // Lesser General Public License for more details. 19 | // 20 | // You should have received a copy of the GNU Lesser General Public 21 | // License along with FFmpegWrapper; if not, write to the Free Software 22 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 | // 24 | 25 | #import "FFmpegWrapper.h" 26 | #import "libavformat/avformat.h" 27 | #import "libavcodec/avcodec.h" 28 | #import "libavutil/intreadwrite.h" 29 | #import "libavutil/timestamp.h" 30 | #import "libavutil/log.h" 31 | 32 | #import "FFInputFile.h" 33 | #import "FFOutputFile.h" 34 | #import "FFInputStream.h" 35 | #import "FFOutputStream.h" 36 | #import "FFBitstreamFilter.h" 37 | 38 | #define VSYNC_AUTO -1 39 | #define VSYNC_PASSTHROUGH 0 40 | #define VSYNC_CFR 1 41 | #define VSYNC_VFR 2 42 | #define VSYNC_DROP 0xff 43 | 44 | @implementation FFmpegWrapper 45 | @synthesize conversionQueue, callbackQueue; 46 | 47 | - (void) dealloc { 48 | avformat_network_deinit(); 49 | } 50 | 51 | - (id) init { 52 | if (self = [super init]) { 53 | self.conversionQueue = dispatch_queue_create("ffmpeg conversion queue", NULL); 54 | self.callbackQueue = dispatch_get_main_queue(); 55 | av_register_all(); 56 | avformat_network_init(); 57 | avcodec_register_all(); 58 | #if DEBUG 59 | av_log_set_level(AV_LOG_VERBOSE); 60 | #else 61 | av_log_set_level(AV_LOG_QUIET); 62 | #endif 63 | 64 | } 65 | return self; 66 | } 67 | 68 | - (void) setupDirectStreamCopyFromInputFile:(FFInputFile*)inputFile outputFile:(FFOutputFile*)outputFile { 69 | // Set the output streams to be the same as input streams 70 | NSUInteger inputStreamCount = inputFile.streams.count; 71 | for (int i = 0; i < inputStreamCount; i++) { 72 | FFInputStream *inputStream = [inputFile.streams objectAtIndex:i]; 73 | FFOutputStream *outputStream = [[FFOutputStream alloc] initWithOutputFile:outputFile outputCodec:[inputStream codecName]]; 74 | AVCodecContext *inputCodecContext = inputStream.stream->codec; 75 | AVCodecContext *outputCodecContext = outputStream.stream->codec; 76 | avcodec_copy_context(outputCodecContext, inputCodecContext); 77 | } 78 | } 79 | 80 | - (void) finishWithSuccess:(BOOL)success error:(NSError*)error completionBlock:(FFmpegWrapperCompletionBlock)completionBlock { 81 | if (completionBlock) { 82 | dispatch_async(callbackQueue, ^{ 83 | completionBlock(success, error); 84 | }); 85 | } 86 | } 87 | 88 | - (void) convertInputPath:(NSString*)inputPath outputPath:(NSString*)outputPath options:(NSDictionary*)options progressBlock:(FFmpegWrapperProgressBlock)progressBlock completionBlock:(FFmpegWrapperCompletionBlock)completionBlock { 89 | dispatch_async(conversionQueue, ^{ 90 | FFInputFile *inputFile = nil; 91 | FFOutputFile *outputFile = nil; 92 | NSError *error = nil; 93 | NSFileManager *fileManager = [NSFileManager defaultManager]; 94 | NSDictionary *inputFileAttributes = [fileManager attributesOfItemAtPath:inputPath error:&error]; 95 | if (error) { 96 | [self finishWithSuccess:NO error:error completionBlock:completionBlock]; 97 | return; 98 | } 99 | uint64_t totalBytesExpectedToRead = [[inputFileAttributes objectForKey:NSFileSize] unsignedLongLongValue]; 100 | uint64_t totalBytesRead = 0; 101 | 102 | // Open the input file for reading 103 | inputFile = [[FFInputFile alloc] initWithPath:inputPath options:options]; 104 | 105 | // Open output format context 106 | outputFile = [[FFOutputFile alloc] initWithPath:outputPath options:options]; 107 | 108 | // Copy settings from input context to output context for direct stream copy 109 | [self setupDirectStreamCopyFromInputFile:inputFile outputFile:outputFile]; 110 | 111 | // Open the output file for writing and write header 112 | if (![outputFile openFileForWritingWithError:&error]) { 113 | [self finishWithSuccess:NO error:error completionBlock:completionBlock]; 114 | return; 115 | } 116 | if (![outputFile writeHeaderWithError:&error]) { 117 | [self finishWithSuccess:NO error:error completionBlock:completionBlock]; 118 | return; 119 | } 120 | 121 | FFBitstreamFilter *bitstreamFilter = [[FFBitstreamFilter alloc] initWithFilterName:@"h264_mp4toannexb"]; 122 | [outputFile addBitstreamFilter:bitstreamFilter]; 123 | 124 | // Read the input file 125 | BOOL continueReading = YES; 126 | AVPacket *packet = av_malloc(sizeof(AVPacket)); 127 | while (continueReading) { 128 | continueReading = [inputFile readFrameIntoPacket:packet error:&error]; 129 | if (error) { 130 | [self finishWithSuccess:NO error:error completionBlock:completionBlock]; 131 | return; 132 | } 133 | if (!continueReading) { 134 | break; 135 | } 136 | 137 | FFInputStream *inputStream = [inputFile.streams objectAtIndex:packet->stream_index]; 138 | FFOutputStream *outputStream = [outputFile.streams objectAtIndex:packet->stream_index]; 139 | 140 | packet->pts = av_rescale_q(packet->pts, inputStream.stream->time_base, outputStream.stream->time_base); 141 | packet->dts = av_rescale_q(packet->dts, inputStream.stream->time_base, outputStream.stream->time_base); 142 | 143 | totalBytesRead += packet->size; 144 | 145 | if (![outputFile writePacket:packet error:&error]) { 146 | [self finishWithSuccess:NO error:error completionBlock:completionBlock]; 147 | return; 148 | } 149 | 150 | if (progressBlock) { 151 | dispatch_async(callbackQueue, ^{ 152 | progressBlock(packet->size, totalBytesRead, totalBytesExpectedToRead); 153 | }); 154 | } 155 | av_free_packet(packet); 156 | } 157 | 158 | if (![outputFile writeTrailerWithError:&error]) { 159 | [self finishWithSuccess:NO error:error completionBlock:completionBlock]; 160 | return; 161 | } 162 | 163 | // Yay looks good! 164 | [self finishWithSuccess:YES error:nil completionBlock:completionBlock]; 165 | }); 166 | } 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | FFmpegWrapper 2 | 3 | Created by Christopher Ballinger on 9/14/13. 4 | Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 5 | 6 | FFmpegWrapper is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | FFmpegWrapper 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 GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with FFmpegWrapper; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FFmpegWrapper 2 | 3 | FFmpegWrapper is a lightweight Objective-C wrapper for some FFmpeg libav functions. 4 | 5 | ## Installation 6 | 7 | Note: This project includes [FFmpeg-iOS](https://github.com/chrisballinger/FFmpeg-iOS) as submodule which you will need to build separately. 8 | 9 | 1. Add this as a git submodule to your project. 10 | 11 | $ git submodule add Submodules/FFmpegWrapper https://github.com/OpenWatch/FFmpegWrapper.git 12 | 13 | 2. Drag `FFmpegWrapper.xcodeproj` into your project's files. 14 | 3. Add `FFmpegWrapper` to your target's Target Dependencies in Build Phases. 15 | 4. Add `libFFmpegWrapper.a` to your target's Link Binary with Libraries in Build Phases. 16 | 17 | ## Usage 18 | 19 | `FFmpegWrapper.h` contains the latest documentation so it would be advisable to check there first as this document may be out of date due to rapid development. 20 | 21 | Converts file at `inputPath` to a new file at `outputPath` using the parameters specified in the `options` dictionary. The two optional callbacks are for monitoring the progress and completion of a queued task and are always called on the main thread. All calls to this function are currently queued in a synchronous internal dispatch queue. 22 | 23 | - (void) convertInputPath:(NSString*)inputPath outputPath:(NSString*)outputPath options:(NSDictionary*)options progressBlock:(FFmpegWrapperProgressBlock)progressBlock completionBlock:(FFmpegWrapperCompletionBlock)completionBlock; 24 | 25 | ## License 26 | 27 | Like [FFmpeg](http://www.ffmpeg.org) itself, this library is LGPL 2.1+. 28 | 29 | FFmpegWrapper 30 | 31 | Created by Christopher Ballinger on 9/14/13. 32 | Copyright (c) 2013 OpenWatch, Inc. All rights reserved. 33 | 34 | FFmpegWrapper is free software; you can redistribute it and/or 35 | modify it under the terms of the GNU Lesser General Public 36 | License as published by the Free Software Foundation; either 37 | version 2.1 of the License, or (at your option) any later version. 38 | 39 | FFmpegWrapper is distributed in the hope that it will be useful, 40 | but WITHOUT ANY WARRANTY; without even the implied warranty of 41 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 42 | Lesser General Public License for more details. 43 | 44 | You should have received a copy of the GNU Lesser General Public 45 | License along with FFmpegWrapper; if not, write to the Free Software 46 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA --------------------------------------------------------------------------------