mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 04:26:37 +08:00 
			
		
		
		
	 9261e6cf3f
			
		
	
	9261e6cf3f
	
	
	
		
			
			This avoids clashes if we internally want to override the global open function. Signed-off-by: Martin Storsjö <martin@martin.st>
		
			
				
	
	
		
			155 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * RTP VP8 Depacketizer
 | |
|  * Copyright (c) 2010 Josh Allmann
 | |
|  *
 | |
|  * This file is part of Libav.
 | |
|  *
 | |
|  * Libav 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.
 | |
|  *
 | |
|  * Libav 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 Libav; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * @file
 | |
|  * @brief RTP support for the VP8 payload
 | |
|  * @author Josh Allmann <joshua.allmann@gmail.com>
 | |
|  * ( http://www.webmproject.org/code/specs/rtp/ )
 | |
|  */
 | |
| 
 | |
| #include "libavcodec/bytestream.h"
 | |
| 
 | |
| #include "rtpdec_formats.h"
 | |
| 
 | |
| struct PayloadContext {
 | |
|     AVIOContext *data;
 | |
|     uint32_t       timestamp;
 | |
|     int is_keyframe;
 | |
| };
 | |
| 
 | |
| static void prepare_packet(AVPacket *pkt, PayloadContext *vp8, int stream)
 | |
| {
 | |
|     av_init_packet(pkt);
 | |
|     pkt->stream_index = stream;
 | |
|     pkt->flags        = vp8->is_keyframe ? AV_PKT_FLAG_KEY : 0;
 | |
|     pkt->size         = avio_close_dyn_buf(vp8->data, &pkt->data);
 | |
|     pkt->destruct     = av_destruct_packet;
 | |
|     vp8->data         = NULL;
 | |
| }
 | |
| 
 | |
| static int vp8_handle_packet(AVFormatContext *ctx,
 | |
|                              PayloadContext *vp8,
 | |
|                              AVStream *st,
 | |
|                              AVPacket *pkt,
 | |
|                              uint32_t *timestamp,
 | |
|                              const uint8_t *buf,
 | |
|                              int len, int flags)
 | |
| {
 | |
|     int start_packet, end_packet, has_au, ret = AVERROR(EAGAIN);
 | |
| 
 | |
|     if (!buf) {
 | |
|         // only called when vp8_handle_packet returns 1
 | |
|         if (!vp8->data) {
 | |
|             av_log(ctx, AV_LOG_ERROR, "Invalid VP8 data passed\n");
 | |
|             return AVERROR_INVALIDDATA;
 | |
|         }
 | |
|         prepare_packet(pkt, vp8, st->index);
 | |
|         *timestamp = vp8->timestamp;
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     start_packet = *buf & 1;
 | |
|     end_packet   = flags & RTP_FLAG_MARKER;
 | |
|     has_au       = *buf & 2;
 | |
|     buf++;
 | |
|     len--;
 | |
| 
 | |
|     if (start_packet) {
 | |
|         int res;
 | |
|         uint32_t ts = *timestamp;
 | |
|         if (vp8->data) {
 | |
|             // missing end marker; return old frame anyway. untested
 | |
|             prepare_packet(pkt, vp8, st->index);
 | |
|             *timestamp = vp8->timestamp; // reset timestamp from old frame
 | |
| 
 | |
|             // if current frame fits into one rtp packet, need to hold
 | |
|             // that for the next av_get_packet call
 | |
|             ret = end_packet ? 1 : 0;
 | |
|         }
 | |
|         if ((res = avio_open_dyn_buf(&vp8->data)) < 0)
 | |
|             return res;
 | |
|         vp8->is_keyframe = *buf & 1;
 | |
|         vp8->timestamp   = ts;
 | |
|      }
 | |
| 
 | |
|     if (!vp8->data || vp8->timestamp != *timestamp && ret == AVERROR(EAGAIN)) {
 | |
|         av_log(ctx, AV_LOG_WARNING,
 | |
|                "Received no start marker; dropping frame\n");
 | |
|         return AVERROR(EAGAIN);
 | |
|     }
 | |
| 
 | |
|     // cycle through VP8AU headers if needed
 | |
|     // not tested with actual VP8AUs
 | |
|     while (len) {
 | |
|         int au_len = len;
 | |
|         if (has_au && len > 2) {
 | |
|             au_len = AV_RB16(buf);
 | |
|             buf += 2;
 | |
|             len -= 2;
 | |
|             if (buf + au_len > buf + len) {
 | |
|                 av_log(ctx, AV_LOG_ERROR, "Invalid VP8AU length\n");
 | |
|                 return AVERROR_INVALIDDATA;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         avio_write(vp8->data, buf, au_len);
 | |
|         buf += au_len;
 | |
|         len -= au_len;
 | |
|     }
 | |
| 
 | |
|     if (ret != AVERROR(EAGAIN)) // did we miss a end marker?
 | |
|         return ret;
 | |
| 
 | |
|     if (end_packet) {
 | |
|         prepare_packet(pkt, vp8, st->index);
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     return AVERROR(EAGAIN);
 | |
| }
 | |
| 
 | |
| static PayloadContext *vp8_new_context(void)
 | |
| {
 | |
|     av_log(NULL, AV_LOG_ERROR, "RTP VP8 payload implementation is incompatible "
 | |
|                                "with the latest spec drafts.\n");
 | |
|     return av_mallocz(sizeof(PayloadContext));
 | |
| }
 | |
| 
 | |
| static void vp8_free_context(PayloadContext *vp8)
 | |
| {
 | |
|     if (vp8->data) {
 | |
|         uint8_t *tmp;
 | |
|         avio_close_dyn_buf(vp8->data, &tmp);
 | |
|         av_free(tmp);
 | |
|     }
 | |
|     av_free(vp8);
 | |
| }
 | |
| 
 | |
| RTPDynamicProtocolHandler ff_vp8_dynamic_handler = {
 | |
|     .enc_name       = "VP8",
 | |
|     .codec_type     = AVMEDIA_TYPE_VIDEO,
 | |
|     .codec_id       = CODEC_ID_VP8,
 | |
|     .alloc          = vp8_new_context,
 | |
|     .free           = vp8_free_context,
 | |
|     .parse_packet   = vp8_handle_packet,
 | |
| };
 |