You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	FireWire DV/HDV input device using libiec61883
Signed-off-by: Stefano Sabatini <stefasab@gmail.com>
This commit is contained in:
		
				
					committed by
					
						 Stefano Sabatini
						Stefano Sabatini
					
				
			
			
				
	
			
			
			
						parent
						
							6d74e3c6f2
						
					
				
				
					commit
					325fb246f2
				
			| @@ -20,6 +20,7 @@ version next: | ||||
| - SAMI demuxer and decoder | ||||
| - RealText demuxer and decoder | ||||
| - Heart Of Darkness PAF playback support | ||||
| - iec61883 device | ||||
|  | ||||
|  | ||||
| version 0.11: | ||||
|   | ||||
| @@ -263,6 +263,7 @@ libavdevice | ||||
|     libavdevice/avdevice.h | ||||
|  | ||||
|  | ||||
|   iec61883.c                            Georg Lippitsch | ||||
|   libdc1394.c                           Roman Shaposhnik | ||||
|   v4l2.c                                Luca Abeni | ||||
|   vfwcap.c                              Ramiro Polla | ||||
|   | ||||
							
								
								
									
										3
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -1677,6 +1677,7 @@ dshow_indev_deps="IBaseFilter" | ||||
| dshow_indev_extralibs="-lpsapi -lole32 -lstrmiids -luuid" | ||||
| dv1394_indev_deps="dv1394 dv_demuxer" | ||||
| fbdev_indev_deps="linux_fb_h" | ||||
| iec61883_indev_deps="iec61883" | ||||
| jack_indev_deps="jack_jack_h sem_timedwait" | ||||
| lavfi_indev_deps="avfilter" | ||||
| libcdio_indev_deps="libcdio" | ||||
| @@ -2820,6 +2821,7 @@ case $target_os in | ||||
|     linux) | ||||
|         add_cppflags -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 | ||||
|         enable dv1394 | ||||
|         enable iec61883 | ||||
|         ;; | ||||
|     irix*) | ||||
|         target_os=irix | ||||
| @@ -3285,6 +3287,7 @@ enabled avisynth   && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32 | ||||
| enabled fontconfig && require_pkg_config fontconfig "fontconfig/fontconfig.h" FcInit | ||||
| enabled frei0r     && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; } | ||||
| enabled gnutls     && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init | ||||
| enabled iec61883   && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883 | ||||
| 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 | ||||
|   | ||||
| @@ -179,6 +179,55 @@ ffmpeg -f fbdev -frames:v 1 -r 1 -i /dev/fb0 screenshot.jpeg | ||||
|  | ||||
| See also @url{http://linux-fbdev.sourceforge.net/}, and fbset(1). | ||||
|  | ||||
| @section iec61883 | ||||
|  | ||||
| FireWire DV/HDV input device using libiec61883. | ||||
|  | ||||
| The iec61883 capture device supports capturing from a video device | ||||
| connected via IEEE1394 (FireWire), using libiec61883 and the new Linux | ||||
| FireWire stack (juju). This is the default DV/HDV input method in Linux | ||||
| Kernel 2.6.37 and later, since the old FireWire stack was removed. | ||||
|  | ||||
| Specify the FireWire port to be used as input file, or "auto" | ||||
| to choose the first port connected. | ||||
|  | ||||
| @subsection Options | ||||
|  | ||||
| @table @option | ||||
|  | ||||
| @item dvtype | ||||
| Override autodetection of DV/HDV. This should only be used if auto | ||||
| detection does not work, or if usage of a different device type | ||||
| should be prohibited. Treating a DV device as HDV (or vice versa) will | ||||
| not work and result in undefined behavior. | ||||
| The values @option{auto}, @option{dv} and @option{hdv} are supported. | ||||
|  | ||||
| @item dvbuffer | ||||
| Set maxiumum size of buffer for incoming data, in frames. For DV, this | ||||
| is an exact value. For HDV, it is not frame exact, since HDV does | ||||
| not have a fixed frame size. | ||||
|  | ||||
| @end table | ||||
|  | ||||
| @subsection Examples | ||||
|  | ||||
| @itemize | ||||
|  | ||||
| @item | ||||
| Grab and show the input of a FireWire DV/HDV device. | ||||
| @example | ||||
| ffplay -f iec61883 -i auto | ||||
| @end example | ||||
|  | ||||
| @item | ||||
| Grab and record the input of a FireWire DV/HDV device, | ||||
| using a packet buffer of 100000 packets if the source is HDV. | ||||
| @example | ||||
| ffmpeg -f iec61883 -i auto -hdvbuffer 100000 out.mpg | ||||
| @end example | ||||
|  | ||||
| @end itemize | ||||
|  | ||||
| @section jack | ||||
|  | ||||
| JACK input device. | ||||
|   | ||||
| @@ -21,6 +21,7 @@ OBJS-$(CONFIG_DSHOW_INDEV)               += dshow.o dshow_enummediatypes.o \ | ||||
|                                             dshow_pin.o dshow_common.o | ||||
| OBJS-$(CONFIG_DV1394_INDEV)              += dv1394.o | ||||
| OBJS-$(CONFIG_FBDEV_INDEV)               += fbdev.o | ||||
| OBJS-$(CONFIG_IEC61883_INDEV)            += iec61883.o | ||||
| OBJS-$(CONFIG_JACK_INDEV)                += jack_audio.o timefilter.o | ||||
| OBJS-$(CONFIG_LAVFI_INDEV)               += lavfi.o | ||||
| OBJS-$(CONFIG_OPENAL_INDEV)              += openal-dec.o | ||||
|   | ||||
| @@ -43,6 +43,7 @@ void avdevice_register_all(void) | ||||
|     REGISTER_INDEV    (DSHOW, dshow); | ||||
|     REGISTER_INDEV    (DV1394, dv1394); | ||||
|     REGISTER_INDEV    (FBDEV, fbdev); | ||||
|     REGISTER_INDEV    (IEC61883, iec61883); | ||||
|     REGISTER_INDEV    (JACK, jack); | ||||
|     REGISTER_INDEV    (LAVFI, lavfi); | ||||
|     REGISTER_INDEV    (OPENAL, openal); | ||||
|   | ||||
							
								
								
									
										466
									
								
								libavdevice/iec61883.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								libavdevice/iec61883.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,466 @@ | ||||
| /* | ||||
|  * Copyright (c) 2012 Georg Lippitsch <georg.lippitsch@gmx.at> | ||||
|  * | ||||
|  * 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 | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @file | ||||
|  * libiec61883 interface | ||||
|  */ | ||||
|  | ||||
| #include <sys/poll.h> | ||||
| #include <libraw1394/raw1394.h> | ||||
| #include <libavc1394/avc1394.h> | ||||
| #include <libavc1394/rom1394.h> | ||||
| #include <libiec61883/iec61883.h> | ||||
| #include "libavformat/dv.h" | ||||
| #include "libavformat/mpegts.h" | ||||
| #include "libavutil/opt.h" | ||||
| #include "avdevice.h" | ||||
|  | ||||
| #define THREADS HAVE_PTHREADS | ||||
|  | ||||
| #if THREADS | ||||
| #include <pthread.h> | ||||
| #endif | ||||
|  | ||||
| #define MOTDCT_SPEC_ID      0x00005068 | ||||
| #define IEC61883_AUTO       0 | ||||
| #define IEC61883_DV         1 | ||||
| #define IEC61883_HDV        2 | ||||
|  | ||||
| /** | ||||
|  * For DV, one packet corresponds exactly to one frame. | ||||
|  * For HDV, these are MPEG2 transport stream packets. | ||||
|  * The queue is implemented as linked list. | ||||
|  */ | ||||
| typedef struct DVPacket { | ||||
|     uint8_t *buf;                       ///< actual buffer data | ||||
|     int len;                            ///< size of buffer allocated | ||||
|     struct DVPacket *next;              ///< next DVPacket | ||||
| } DVPacket; | ||||
|  | ||||
| struct iec61883_data { | ||||
|     AVClass *class; | ||||
|     raw1394handle_t raw1394;            ///< handle for libraw1394 | ||||
|     iec61883_dv_fb_t iec61883_dv;       ///< handle for libiec61883 when used with DV | ||||
|     iec61883_mpeg2_t iec61883_mpeg2;    ///< handle for libiec61883 when used with HDV | ||||
|  | ||||
|     DVDemuxContext *dv_demux;           ///< generic DV muxing/demuxing context | ||||
|     MpegTSContext *mpeg_demux;          ///< generic HDV muxing/demuxing context | ||||
|  | ||||
|     DVPacket *queue_first;              ///< first element of packet queue | ||||
|     DVPacket *queue_last;               ///< last element of packet queue | ||||
|  | ||||
|     int packets;                        ///< Number of packets queued | ||||
|     int max_packets;                    ///< Max. number of packets in queue | ||||
|  | ||||
|     int bandwidth;                      ///< returned by libiec61883 | ||||
|     int channel;                        ///< returned by libiec61883 | ||||
|     int input_port;                     ///< returned by libiec61883 | ||||
|     int type;                           ///< Stream type, to distinguish DV/HDV | ||||
|     int node;                           ///< returned by libiec61883 | ||||
|     int output_port;                    ///< returned by libiec61883 | ||||
|     int thread_loop;                    ///< Condition for thread while-loop | ||||
|     int receiving;                      ///< True as soon data from device available | ||||
|     int receive_error;                  ///< Set in receive task in case of error | ||||
|     int eof;                            ///< True as soon as no more data available | ||||
|  | ||||
|     struct pollfd raw1394_poll;         ///< to poll for new data from libraw1394 | ||||
|  | ||||
|     /** Parse function for DV/HDV differs, so this is set before packets arrive */ | ||||
|     int (*parse_queue)(struct iec61883_data *dv, AVPacket *pkt); | ||||
|  | ||||
| #if THREADS | ||||
|     pthread_t receive_task_thread; | ||||
|     pthread_mutex_t mutex; | ||||
|     pthread_cond_t cond; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| static int iec61883_callback(unsigned char *data, int length, | ||||
|                              int complete, void *callback_data) | ||||
| { | ||||
|     struct iec61883_data *dv = callback_data; | ||||
|     DVPacket *packet; | ||||
|     int ret; | ||||
|  | ||||
| #ifdef THREADS | ||||
|     pthread_mutex_lock(&dv->mutex); | ||||
| #endif | ||||
|  | ||||
|     if (dv->packets >= dv->max_packets) { | ||||
|         av_log(NULL, AV_LOG_ERROR, "DV packet queue overrun, dropping.\n"); | ||||
|         ret = 0; | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     packet = av_mallocz(sizeof(*packet)); | ||||
|     if (!packet) { | ||||
|         ret = -1; | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     packet->buf = av_malloc(length); | ||||
|     if (!packet->buf) { | ||||
|         ret = -1; | ||||
|         goto exit; | ||||
|     } | ||||
|     packet->len = length; | ||||
|  | ||||
|     memcpy(packet->buf, data, length); | ||||
|  | ||||
|     if (dv->queue_first) { | ||||
|         dv->queue_last->next = packet; | ||||
|         dv->queue_last = packet; | ||||
|     } else { | ||||
|         dv->queue_first = packet; | ||||
|         dv->queue_last = packet; | ||||
|     } | ||||
|     dv->packets++; | ||||
|  | ||||
|     ret = 0; | ||||
|  | ||||
| exit: | ||||
| #ifdef THREADS | ||||
|     pthread_cond_signal(&dv->cond); | ||||
|     pthread_mutex_unlock(&dv->mutex); | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static void *iec61883_receive_task(void *opaque) | ||||
| { | ||||
|     struct iec61883_data *dv = (struct iec61883_data *)opaque; | ||||
|     int result; | ||||
|  | ||||
| #ifdef THREADS | ||||
|     while (dv->thread_loop) | ||||
| #endif | ||||
|     { | ||||
|         while ((result = poll(&dv->raw1394_poll, 1, 200)) < 0) { | ||||
|             if (!(errno == EAGAIN || errno == EINTR)) { | ||||
|                 av_log(NULL, AV_LOG_ERROR, "Raw1394 poll error occurred.\n"); | ||||
|                 dv->receive_error = AVERROR(EIO); | ||||
|                 return NULL; | ||||
|             } | ||||
|         } | ||||
|         if (result > 0 && ((dv->raw1394_poll.revents & POLLIN) | ||||
|                            || (dv->raw1394_poll.revents & POLLPRI))) { | ||||
|             dv->receiving = 1; | ||||
|             raw1394_loop_iterate(dv->raw1394); | ||||
|         } else if (dv->receiving) { | ||||
|             av_log(NULL, AV_LOG_ERROR, "No more input data available\n"); | ||||
| #ifdef THREADS | ||||
|             pthread_mutex_lock(&dv->mutex); | ||||
|             dv->eof = 1; | ||||
|             pthread_cond_signal(&dv->cond); | ||||
|             pthread_mutex_unlock(&dv->mutex); | ||||
| #else | ||||
|             dv->eof = 1; | ||||
| #endif | ||||
|             return NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| static int iec61883_parse_queue_dv(struct iec61883_data *dv, AVPacket *pkt) | ||||
| { | ||||
|     DVPacket *packet; | ||||
|     int size; | ||||
|  | ||||
|     size = avpriv_dv_get_packet(dv->dv_demux, pkt); | ||||
|     if (size > 0) | ||||
|         return size; | ||||
|  | ||||
|     packet = dv->queue_first; | ||||
|     if (!packet) | ||||
|         return -1; | ||||
|  | ||||
|     size = avpriv_dv_produce_packet(dv->dv_demux, pkt, | ||||
|                                     packet->buf, packet->len, -1); | ||||
|     pkt->destruct = av_destruct_packet; | ||||
|     dv->queue_first = packet->next; | ||||
|     av_free(packet); | ||||
|     dv->packets--; | ||||
|  | ||||
|     if (size > 0) | ||||
|         return size; | ||||
|  | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt) | ||||
| { | ||||
|     DVPacket *packet; | ||||
|     int size; | ||||
|  | ||||
|     while (dv->queue_first) { | ||||
|         packet = dv->queue_first; | ||||
|         size = ff_mpegts_parse_packet(dv->mpeg_demux, pkt, packet->buf, | ||||
|                                       packet->len); | ||||
|         dv->queue_first = packet->next; | ||||
|         av_free(packet->buf); | ||||
|         av_free(packet); | ||||
|         dv->packets--; | ||||
|  | ||||
|         if (size > 0) | ||||
|             return size; | ||||
|     } | ||||
|  | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| static int iec61883_read_header(AVFormatContext *context) | ||||
| { | ||||
|     struct iec61883_data *dv = context->priv_data; | ||||
|     struct raw1394_portinfo pinf[16]; | ||||
|     rom1394_directory rom_dir; | ||||
|     char *endptr; | ||||
|     int inport; | ||||
|     int nb_ports; | ||||
|     int port = -1; | ||||
|     int response; | ||||
|     int i, j = 0; | ||||
|  | ||||
|     dv->input_port = -1; | ||||
|     dv->output_port = -1; | ||||
|     dv->channel = -1; | ||||
|  | ||||
|     dv->raw1394 = raw1394_new_handle(); | ||||
|  | ||||
|     if (!dv->raw1394) { | ||||
|         av_log(context, AV_LOG_ERROR, "Failed to open IEEE1394 interface.\n"); | ||||
|         return AVERROR(EIO); | ||||
|     } | ||||
|  | ||||
|     if ((nb_ports = raw1394_get_port_info(dv->raw1394, pinf, 16)) < 0) { | ||||
|         av_log(context, AV_LOG_ERROR, "Failed to get number of IEEE1394 ports.\n"); | ||||
|         goto fail; | ||||
|     } | ||||
|  | ||||
|     inport = strtol(context->filename, &endptr, 10); | ||||
|     if (endptr != context->filename && *endptr == '\0') { | ||||
|         av_log(context, AV_LOG_INFO, "Selecting IEEE1394 port: %d\n", inport); | ||||
|         j = inport; | ||||
|         nb_ports = inport + 1; | ||||
|     } else if (strcmp(context->filename, "auto")) { | ||||
|         av_log(context, AV_LOG_ERROR, "Invalid input \"%s\", you should specify " | ||||
|                "\"auto\" for auto-detection, or the port number.\n", context->filename); | ||||
|         goto fail; | ||||
|     } | ||||
|  | ||||
|     /* Select first AV/C tape recorder player node */ | ||||
|  | ||||
|     for (; j < nb_ports && port==-1; ++j) { | ||||
|         if (raw1394_set_port(dv->raw1394, j)) { | ||||
|             av_log(context, AV_LOG_ERROR, "Failed setting IEEE1394 port.\n"); | ||||
|             goto fail; | ||||
|         } | ||||
|         for (i=0; i<raw1394_get_nodecount(dv->raw1394); ++i) { | ||||
|             if (rom1394_get_directory(dv->raw1394, i, &rom_dir) < 0) | ||||
|                 continue; | ||||
|             if (((rom1394_get_node_type(&rom_dir) == ROM1394_NODE_TYPE_AVC) && | ||||
|                  avc1394_check_subunit_type(dv->raw1394, i, AVC1394_SUBUNIT_TYPE_VCR)) || | ||||
|                 (rom_dir.unit_spec_id == MOTDCT_SPEC_ID)) { | ||||
|                 rom1394_free_directory(&rom_dir); | ||||
|                 dv->node = i; | ||||
|                 port = j; | ||||
|                 break; | ||||
|             } | ||||
|             rom1394_free_directory(&rom_dir); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (port == -1) { | ||||
|         av_log(context, AV_LOG_ERROR, "No AV/C devices found.\n"); | ||||
|         goto fail; | ||||
|     } | ||||
|  | ||||
|     /* Find out if device is DV or HDV */ | ||||
|  | ||||
|     if (dv->type == IEC61883_AUTO) { | ||||
|         response = avc1394_transaction(dv->raw1394, dv->node, | ||||
|                                        AVC1394_CTYPE_STATUS | | ||||
|                                        AVC1394_SUBUNIT_TYPE_TAPE_RECORDER | | ||||
|                                        AVC1394_SUBUNIT_ID_0 | | ||||
|                                        AVC1394_VCR_COMMAND_OUTPUT_SIGNAL_MODE | | ||||
|                                        0xFF, 2); | ||||
|         response = AVC1394_GET_OPERAND0(response); | ||||
|         dv->type = (response == 0x10 || response == 0x90 || response == 0x1A || response == 0x9A) ? | ||||
|             IEC61883_HDV : IEC61883_DV; | ||||
|     } | ||||
|  | ||||
|     /* Connect to device, and do initialization */ | ||||
|  | ||||
|     dv->channel = iec61883_cmp_connect(dv->raw1394, dv->node, &dv->output_port, | ||||
|                                        raw1394_get_local_id(dv->raw1394), | ||||
|                                        &dv->input_port, &dv->bandwidth); | ||||
|  | ||||
|     if (dv->channel < 0) | ||||
|         dv->channel = 63; | ||||
|  | ||||
|     if (!dv->max_packets) | ||||
|         dv->max_packets = 100; | ||||
|  | ||||
|     if (dv->type == IEC61883_HDV) { | ||||
|  | ||||
|         /* Init HDV receive */ | ||||
|  | ||||
|         avformat_new_stream(context, NULL); | ||||
|  | ||||
|         dv->mpeg_demux = ff_mpegts_parse_open(context); | ||||
|         if (!dv->mpeg_demux) | ||||
|             goto fail; | ||||
|  | ||||
|         dv->parse_queue = iec61883_parse_queue_hdv; | ||||
|  | ||||
|         dv->iec61883_mpeg2 = iec61883_mpeg2_recv_init(dv->raw1394, | ||||
|                                                       (iec61883_mpeg2_recv_t)iec61883_callback, | ||||
|                                                       dv); | ||||
|  | ||||
|         dv->max_packets *= 766; | ||||
|     } else { | ||||
|  | ||||
|         /* Init DV receive */ | ||||
|  | ||||
|         dv->dv_demux = avpriv_dv_init_demux(context); | ||||
|         if (!dv->dv_demux) | ||||
|             goto fail; | ||||
|  | ||||
|         dv->parse_queue = iec61883_parse_queue_dv; | ||||
|  | ||||
|         dv->iec61883_dv = iec61883_dv_fb_init(dv->raw1394, iec61883_callback, dv); | ||||
|     } | ||||
|  | ||||
|     dv->raw1394_poll.fd = raw1394_get_fd(dv->raw1394); | ||||
|     dv->raw1394_poll.events = POLLIN | POLLERR | POLLHUP | POLLPRI; | ||||
|  | ||||
|     /* Actually start receiving */ | ||||
|  | ||||
|     if (dv->type == IEC61883_HDV) | ||||
|         iec61883_mpeg2_recv_start(dv->iec61883_mpeg2, dv->channel); | ||||
|     else | ||||
|         iec61883_dv_fb_start(dv->iec61883_dv, dv->channel); | ||||
|  | ||||
| #if THREADS | ||||
|     dv->thread_loop = 1; | ||||
|     pthread_mutex_init(&dv->mutex, NULL); | ||||
|     pthread_cond_init(&dv->cond, NULL); | ||||
|     pthread_create(&dv->receive_task_thread, NULL, iec61883_receive_task, dv); | ||||
| #endif | ||||
|  | ||||
|     return 0; | ||||
|  | ||||
| fail: | ||||
|     raw1394_destroy_handle(dv->raw1394); | ||||
|     return AVERROR(EIO); | ||||
| } | ||||
|  | ||||
| static int iec61883_read_packet(AVFormatContext *context, AVPacket *pkt) | ||||
| { | ||||
|     struct iec61883_data *dv = context->priv_data; | ||||
|     int size; | ||||
|  | ||||
|     /** | ||||
|      * Try to parse frames from queue | ||||
|      */ | ||||
|  | ||||
| #ifdef THREADS | ||||
|     pthread_mutex_lock(&dv->mutex); | ||||
|     while ((size = dv->parse_queue(dv, pkt)) == -1) | ||||
|         if (!dv->eof) | ||||
|             pthread_cond_wait(&dv->cond, &dv->mutex); | ||||
|         else | ||||
|             break; | ||||
|     pthread_mutex_unlock(&dv->mutex); | ||||
| #else | ||||
|     int result; | ||||
|     while ((size = dv->parse_queue(dv, pkt)) == -1) { | ||||
|         iec61883_receive_task((void *)dv); | ||||
|         if (dv->receive_error) | ||||
|             return dv->receive_error; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     return size; | ||||
| } | ||||
|  | ||||
| static int iec61883_close(AVFormatContext *context) | ||||
| { | ||||
|     struct iec61883_data *dv = context->priv_data; | ||||
|  | ||||
| #if THREADS | ||||
|     dv->thread_loop = 0; | ||||
|     pthread_join(dv->receive_task_thread, NULL); | ||||
|     pthread_cond_destroy(&dv->cond); | ||||
|     pthread_mutex_destroy(&dv->mutex); | ||||
| #endif | ||||
|  | ||||
|     if (dv->type == IEC61883_HDV) { | ||||
|         iec61883_mpeg2_recv_stop(dv->iec61883_mpeg2); | ||||
|         iec61883_mpeg2_close(dv->iec61883_mpeg2); | ||||
|         ff_mpegts_parse_close(dv->mpeg_demux); | ||||
|     } else { | ||||
|         iec61883_dv_fb_stop(dv->iec61883_dv); | ||||
|         iec61883_dv_fb_close(dv->iec61883_dv); | ||||
|     } | ||||
|     while (dv->queue_first) { | ||||
|         DVPacket *packet = dv->queue_first; | ||||
|         dv->queue_first = packet->next; | ||||
|         av_free(packet->buf); | ||||
|         av_free(packet); | ||||
|     } | ||||
|  | ||||
|     iec61883_cmp_disconnect(dv->raw1394, dv->node, dv->output_port, | ||||
|                             raw1394_get_local_id(dv->raw1394), | ||||
|                             dv->input_port, dv->channel, dv->bandwidth); | ||||
|  | ||||
|     raw1394_destroy_handle(dv->raw1394); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static const AVOption options[] = { | ||||
|     { "dvtype", "override autodetection of DV/HDV", offsetof(struct iec61883_data, type), AV_OPT_TYPE_INT, {.dbl = IEC61883_AUTO}, IEC61883_AUTO, IEC61883_HDV, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, | ||||
|     { "auto",   "auto detect DV/HDV", 0, AV_OPT_TYPE_CONST, {.dbl = IEC61883_AUTO}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, | ||||
|     { "dv",     "force device being treated as DV device", 0, AV_OPT_TYPE_CONST, {.dbl = IEC61883_DV},   0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, | ||||
|     { "hdv" ,   "force device being treated as HDV device", 0, AV_OPT_TYPE_CONST, {.dbl = IEC61883_HDV},  0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" }, | ||||
|     { "dvbuffer", "set queue buffer size (in packets)", offsetof(struct iec61883_data, max_packets), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, | ||||
|     { NULL }, | ||||
| }; | ||||
|  | ||||
| static const AVClass iec61883_class = { | ||||
|     .class_name = "iec61883 indev", | ||||
|     .item_name  = av_default_item_name, | ||||
|     .option     = options, | ||||
|     .version    = LIBAVUTIL_VERSION_INT, | ||||
| }; | ||||
|  | ||||
| AVInputFormat ff_iec61883_demuxer = { | ||||
|     .name           = "iec61883", | ||||
|     .long_name      = NULL_IF_CONFIG_SMALL("libiec61883 (new DV1394) A/V input device"), | ||||
|     .priv_data_size = sizeof(struct iec61883_data), | ||||
|     .read_header    = iec61883_read_header, | ||||
|     .read_packet    = iec61883_read_packet, | ||||
|     .read_close     = iec61883_close, | ||||
|     .flags          = AVFMT_NOFILE, | ||||
|     .priv_class     = &iec61883_class, | ||||
| }; | ||||
| @@ -28,7 +28,7 @@ | ||||
| #include "libavutil/avutil.h" | ||||
|  | ||||
| #define LIBAVDEVICE_VERSION_MAJOR  54 | ||||
| #define LIBAVDEVICE_VERSION_MINOR   0 | ||||
| #define LIBAVDEVICE_VERSION_MINOR   1 | ||||
| #define LIBAVDEVICE_VERSION_MICRO 100 | ||||
|  | ||||
| #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ | ||||
|   | ||||
| @@ -6,6 +6,9 @@ LIBAVFORMAT_$MAJOR { | ||||
|                 ffm_set_write_index; | ||||
|                 ffm_read_write_index; | ||||
|                 ffm_write_write_index; | ||||
|                 ff_mpegts_parse_close; | ||||
|                 ff_mpegts_parse_open; | ||||
|                 ff_mpegts_parse_packet; | ||||
|                 ff_rtsp_parse_line; | ||||
|                 ff_rtp_get_local_rtp_port; | ||||
|                 ff_rtp_get_local_rtcp_port; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user