bluray protocol
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
		
							parent
							
								
									70b5583baa
								
							
						
					
					
						commit
						23a5bf9db0
					
				| @ -10,6 +10,7 @@ version next: | ||||
| - Sun Rasterfile Encoder | ||||
| - ID3v2 attached pictures reading and writing | ||||
| - WMA Lossless decoder | ||||
| - bluray protocol | ||||
| 
 | ||||
| 
 | ||||
| version 0.10: | ||||
|  | ||||
| @ -370,6 +370,7 @@ Muxers/Demuxers: | ||||
|   wv.c                                  Kostya Shishkov | ||||
| 
 | ||||
| Protocols: | ||||
|   bluray.c                              Petri Hintukainen | ||||
|   http.c                                Ronald S. Bultje | ||||
|   mms*.c                                Ronald S. Bultje | ||||
|   udp.c                                 Luca Abeni | ||||
|  | ||||
							
								
								
									
										4
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @ -171,6 +171,7 @@ External library support: | ||||
|   --enable-gnutls          enable gnutls [no] | ||||
|   --enable-libaacplus      enable AAC+ encoding via libaacplus [no] | ||||
|   --enable-libass          enable libass subtitles rendering [no] | ||||
|   --enable-libbluray       enable BluRay reading using libbluray [no] | ||||
|   --enable-libcelt         enable CELT decoding via libcelt [no] | ||||
|   --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no] | ||||
|   --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no] | ||||
| @ -1029,6 +1030,7 @@ CONFIG_LIST=" | ||||
|     huffman | ||||
|     libaacplus | ||||
|     libass | ||||
|     libbluray | ||||
|     libcdio | ||||
|     libcelt | ||||
|     libdc1394 | ||||
| @ -1633,6 +1635,7 @@ x11_grab_device_indev_deps="x11grab XShmCreateImage" | ||||
| x11_grab_device_indev_extralibs="-lX11 -lXext -lXfixes" | ||||
| 
 | ||||
| # protocols | ||||
| bluray_protocol_deps="libbluray" | ||||
| gopher_protocol_deps="network" | ||||
| httpproxy_protocol_deps="network" | ||||
| httpproxy_protocol_select="tcp_protocol" | ||||
| @ -3140,6 +3143,7 @@ enabled frei0r     && { check_header frei0r.h || die "ERROR: frei0r.h header not | ||||
| enabled gnutls     && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init | ||||
| enabled libaacplus && require  "libaacplus >= 2.0.0" aacplus.h aacplusEncOpen -laacplus | ||||
| enabled libass     && require_pkg_config libass ass/ass.h ass_library_init | ||||
| enabled libbluray  && require libbluray libbluray/bluray.h bd_open -lbluray | ||||
| enabled libcelt    && require libcelt celt/celt.h celt_decode -lcelt0 && | ||||
|                       { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 || | ||||
|                         die "ERROR: libcelt version must be >= 0.11.0."; } | ||||
|  | ||||
| @ -19,6 +19,36 @@ supported protocols. | ||||
| 
 | ||||
| A description of the currently available protocols follows. | ||||
| 
 | ||||
| @section bluray | ||||
| 
 | ||||
| Read BluRay playlist. | ||||
| 
 | ||||
| The accepted options are: | ||||
| @table @option | ||||
| 
 | ||||
| @item angle | ||||
| BluRay angle | ||||
| 
 | ||||
| @item chapter | ||||
| Start chapter (1...N) | ||||
| 
 | ||||
| @item playlist | ||||
| Playlist to read (BDMV/PLAYLIST/?????.mpls) | ||||
| 
 | ||||
| @end table | ||||
| 
 | ||||
| Examples: | ||||
| 
 | ||||
| Read longest playlist from BluRay mounted to /mnt/bluray: | ||||
| @example | ||||
| bluray:/mnt/bluray | ||||
| @end example | ||||
| 
 | ||||
| Read angle 2 of playlist 4 from BluRay mounted to /mnt/bluray, start from chapter 2: | ||||
| @example | ||||
| -playlist 4 -angle 2 -chapter 2 bluray:/mnt/bluray | ||||
| @end example | ||||
| 
 | ||||
| @section concat | ||||
| 
 | ||||
| Physical concatenation protocol. | ||||
|  | ||||
| @ -353,6 +353,7 @@ OBJS-$(CONFIG_LIBRTMP)                   += librtmp.o | ||||
| OBJS+= avio.o aviobuf.o | ||||
| 
 | ||||
| OBJS-$(CONFIG_APPLEHTTP_PROTOCOL)        += hlsproto.o | ||||
| OBJS-$(CONFIG_BLURAY_PROTOCOL)           += bluray.o | ||||
| OBJS-$(CONFIG_CACHE_PROTOCOL)            += cache.o | ||||
| OBJS-$(CONFIG_CONCAT_PROTOCOL)           += concat.o | ||||
| OBJS-$(CONFIG_CRYPTO_PROTOCOL)           += crypto.o | ||||
|  | ||||
| @ -260,6 +260,7 @@ void av_register_all(void) | ||||
| #if FF_API_APPLEHTTP_PROTO | ||||
|     REGISTER_PROTOCOL (APPLEHTTP, applehttp); | ||||
| #endif | ||||
|     REGISTER_PROTOCOL (BLURAY, bluray); | ||||
|     REGISTER_PROTOCOL (CACHE, cache); | ||||
|     REGISTER_PROTOCOL (CONCAT, concat); | ||||
|     REGISTER_PROTOCOL (CRYPTO, crypto); | ||||
|  | ||||
							
								
								
									
										235
									
								
								libavformat/bluray.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								libavformat/bluray.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,235 @@ | ||||
| /*
 | ||||
|  * BluRay (libbluray) protocol | ||||
|  * | ||||
|  * Copyright (c) 2012 Petri Hintukainen <phintuka <at> users.sourceforge.net> | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with FFmpeg; if not, write to the Free Software | ||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  */ | ||||
| 
 | ||||
| #include <libbluray/bluray.h> | ||||
| 
 | ||||
| #include "libavutil/avstring.h" | ||||
| #include "libavformat/avformat.h" | ||||
| #include "libavformat/url.h" | ||||
| #include "libavutil/opt.h" | ||||
| 
 | ||||
| #define BLURAY_PROTO_PREFIX     "bluray:" | ||||
| #define MIN_PLAYLIST_LENGTH     180     /* 3 min */ | ||||
| 
 | ||||
| typedef struct { | ||||
|     const AVClass *class; | ||||
| 
 | ||||
|     BLURAY *bd; | ||||
| 
 | ||||
|     int playlist; | ||||
|     int angle; | ||||
|     int chapter; | ||||
|     /*int region;*/ | ||||
| } BlurayContext; | ||||
| 
 | ||||
| #define OFFSET(x) offsetof(BlurayContext, x) | ||||
| static const AVOption options[] = { | ||||
| {"playlist", "", OFFSET(playlist), AV_OPT_TYPE_INT, { .dbl=-1 }, -1,  99999, AV_OPT_FLAG_DECODING_PARAM }, | ||||
| {"angle",    "", OFFSET(angle),    AV_OPT_TYPE_INT, { .dbl=0 },   0,   0xfe, AV_OPT_FLAG_DECODING_PARAM }, | ||||
| {"chapter",  "", OFFSET(chapter),  AV_OPT_TYPE_INT, { .dbl=1 },   1, 0xfffe, AV_OPT_FLAG_DECODING_PARAM }, | ||||
| /*{"region",   "bluray player region code (1 = region A, 2 = region B, 4 = region C)", OFFSET(region), AV_OPT_TYPE_INT, { .dbl=0 }, 0, 3, AV_OPT_FLAG_DECODING_PARAM },*/ | ||||
| {NULL} | ||||
| }; | ||||
| 
 | ||||
| static const AVClass bluray_context_class = { | ||||
|     .class_name     = "bluray", | ||||
|     .item_name      = av_default_item_name, | ||||
|     .option         = options, | ||||
|     .version        = LIBAVUTIL_VERSION_INT, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static int check_disc_info(URLContext *h) | ||||
| { | ||||
|     BlurayContext *bd = h->priv_data; | ||||
|     const BLURAY_DISC_INFO *disc_info; | ||||
| 
 | ||||
|     disc_info = bd_get_disc_info(bd->bd); | ||||
|     if (!disc_info) { | ||||
|         av_log(h, AV_LOG_ERROR, "bd_get_disc_info() failed\n"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     if (!disc_info->bluray_detected) { | ||||
|         av_log(h, AV_LOG_ERROR, "BluRay disc not detected\n"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     /* AACS */ | ||||
|     if (disc_info->aacs_detected && !disc_info->aacs_handled) { | ||||
|         if (!disc_info->libaacs_detected) { | ||||
|             av_log(h, AV_LOG_ERROR, | ||||
|                    "Media stream encrypted with AACS, install and configure libaacs\n"); | ||||
|         } else { | ||||
|             av_log(h, AV_LOG_ERROR, "Your libaacs can't decrypt this media\n"); | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     /* BD+ */ | ||||
|     if (disc_info->bdplus_detected && !disc_info->bdplus_handled) { | ||||
|         /*
 | ||||
|         if (!disc_info->libbdplus_detected) { | ||||
|             av_log(h, AV_LOG_ERROR, | ||||
|                    "Media stream encrypted with BD+, install and configure libbdplus"); | ||||
|         } else { | ||||
|         */ | ||||
|             av_log(h, AV_LOG_ERROR, "Unable to decrypt BD+ encrypted media"); | ||||
|         /*}*/ | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static int bluray_close(URLContext *h) | ||||
| { | ||||
|     BlurayContext *bd = h->priv_data; | ||||
|     if (bd->bd) { | ||||
|         bd_close(bd->bd); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static int bluray_open(URLContext *h, const char *path, int flags) | ||||
| { | ||||
|     BlurayContext *bd = h->priv_data; | ||||
|     int num_title_idx; | ||||
|     const char *diskname = path; | ||||
| 
 | ||||
|     av_strstart(path, BLURAY_PROTO_PREFIX, &diskname); | ||||
| 
 | ||||
|     bd->bd = bd_open(diskname, NULL); | ||||
|     if (!bd->bd) { | ||||
|         av_log(h, AV_LOG_ERROR, "bd_open() failed\n"); | ||||
|         return AVERROR(EIO); | ||||
|     } | ||||
| 
 | ||||
|     /* check if disc can be played */ | ||||
|     if (check_disc_info(h) < 0) { | ||||
|         return AVERROR(EIO); | ||||
|     } | ||||
| 
 | ||||
|     /* setup player registers */ | ||||
|     /* region code has no effect without menus
 | ||||
|     if (bd->region > 0 && bd->region < 5) { | ||||
|         av_log(h, AV_LOG_INFO, "setting region code to %d (%c)\n", bd->region, 'A' + (bd->region - 1)); | ||||
|         bd_set_player_setting(bd->bd, BLURAY_PLAYER_SETTING_REGION_CODE, bd->region); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     /* load title list */ | ||||
|     num_title_idx = bd_get_titles(bd->bd, TITLES_RELEVANT, MIN_PLAYLIST_LENGTH); | ||||
|     av_log(h, AV_LOG_INFO, "%d usable playlists:\n", num_title_idx); | ||||
|     if (num_title_idx < 1) { | ||||
|         return AVERROR(EIO); | ||||
|     } | ||||
| 
 | ||||
|     /* if playlist was not given, select longest playlist */ | ||||
|     if (bd->playlist < 0) { | ||||
|         uint64_t duration = 0; | ||||
|         int i; | ||||
|         for (i = 0; i < num_title_idx; i++) { | ||||
|             BLURAY_TITLE_INFO *info = bd_get_title_info(bd->bd, i, 0); | ||||
| 
 | ||||
|             av_log(h, AV_LOG_INFO, "playlist %05d.mpls (%d:%02d:%02d)\n", | ||||
|                    info->playlist, | ||||
|                    ((int)(info->duration / 90000) / 3600), | ||||
|                    ((int)(info->duration / 90000) % 3600) / 60, | ||||
|                    ((int)(info->duration / 90000) % 60)); | ||||
| 
 | ||||
|             if (info->duration > duration) { | ||||
|                 bd->playlist = info->playlist; | ||||
|                 duration = info->duration; | ||||
|             } | ||||
| 
 | ||||
|             bd_free_title_info(info); | ||||
|         } | ||||
|         av_log(h, AV_LOG_INFO, "selected %05d.mpls\n", bd->playlist); | ||||
|     } | ||||
| 
 | ||||
|     /* select playlist */ | ||||
|     if (bd_select_playlist(bd->bd, bd->playlist) <= 0) { | ||||
|         av_log(h, AV_LOG_ERROR, "bd_select_playlist(%05d.mpls) failed\n", bd->playlist); | ||||
|         return AVERROR(EIO); | ||||
|     } | ||||
| 
 | ||||
|     /* select angle */ | ||||
|     if (bd->angle >= 0) { | ||||
|         bd_select_angle(bd->bd, bd->angle); | ||||
|     } | ||||
| 
 | ||||
|     /* select chapter */ | ||||
|     if (bd->chapter > 1) { | ||||
|         bd_seek_chapter(bd->bd, bd->chapter - 1); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static int bluray_read(URLContext *h, unsigned char *buf, int size) | ||||
| { | ||||
|     BlurayContext *bd = h->priv_data; | ||||
|     int len; | ||||
| 
 | ||||
|     if (!bd || !bd->bd) { | ||||
|         return AVERROR(EFAULT); | ||||
|     } | ||||
| 
 | ||||
|     len = bd_read(bd->bd, buf, size); | ||||
| 
 | ||||
|     return len; | ||||
| } | ||||
| 
 | ||||
| static int64_t bluray_seek(URLContext *h, int64_t pos, int whence) | ||||
| { | ||||
|     BlurayContext *bd = h->priv_data; | ||||
| 
 | ||||
|     if (!bd || !bd->bd) { | ||||
|         return AVERROR(EFAULT); | ||||
|     } | ||||
| 
 | ||||
|     switch (whence) { | ||||
|     case SEEK_SET: | ||||
|     case SEEK_CUR: | ||||
|     case SEEK_END: | ||||
|         return bd_seek(bd->bd, pos); | ||||
| 
 | ||||
|     case AVSEEK_SIZE: | ||||
|         return bd_get_title_size(bd->bd); | ||||
|     } | ||||
| 
 | ||||
|     av_log(h, AV_LOG_ERROR, "Unsupported whence operation %d\n", whence); | ||||
|     return AVERROR(EINVAL); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| URLProtocol ff_bluray_protocol = { | ||||
|     .name            = "bluray", | ||||
|     .url_close       = bluray_close, | ||||
|     .url_open        = bluray_open, | ||||
|     .url_read        = bluray_read, | ||||
|     .url_seek        = bluray_seek, | ||||
|     .priv_data_size  = sizeof(BlurayContext), | ||||
|     .priv_data_class = &bluray_context_class, | ||||
| }; | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user