From 9d811fd80fbd94a0e44d87cf8ccdab96c2a4af04 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 19 Jun 2012 13:21:09 +0200 Subject: [PATCH 01/19] rtmp: Reduce the number of idle posts sent by sleeping 50ms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rtmpt is effectively half duplex - the server can't return any data unless we send a request (to which the server responds). If we don't have any data to send currently, and the server didn't return any data either, wait a little before doing the next request. This avoids busy looping with idle posts with empty replies, while waiting for more data from the server. Signed-off-by: Martin Storsjö --- libavformat/rtmphttp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libavformat/rtmphttp.c b/libavformat/rtmphttp.c index fdcff50bed..544b493500 100644 --- a/libavformat/rtmphttp.c +++ b/libavformat/rtmphttp.c @@ -24,6 +24,8 @@ * RTMP HTTP protocol */ +#include + #include "libavutil/avstring.h" #include "libavutil/intfloat.h" #include "libavutil/opt.h" @@ -44,6 +46,7 @@ typedef struct RTMP_HTTPContext { int out_capacity; ///< current output buffer capacity int initialized; ///< flag indicating when the http context is initialized int finishing; ///< flag indicating when the client closes the connection + int nb_bytes_read; ///< number of bytes read since the last request } RTMP_HTTPContext; static int rtmp_http_send_cmd(URLContext *h, const char *cmd) @@ -70,6 +73,9 @@ static int rtmp_http_send_cmd(URLContext *h, const char *cmd) if ((ret = ffurl_read(rt->stream, &c, 1)) < 0) return ret; + /* re-init the number of bytes read */ + rt->nb_bytes_read = 0; + return ret; } @@ -117,6 +123,12 @@ static int rtmp_http_read(URLContext *h, uint8_t *buf, int size) if ((ret = rtmp_http_send_cmd(h, "send")) < 0) return ret; } else { + if (rt->nb_bytes_read == 0) { + /* Wait 50ms before retrying to read a server reply in + * order to reduce the number of idle requets. */ + usleep(50000); + } + if ((ret = rtmp_http_write(h, "", 1)) < 0) return ret; @@ -131,6 +143,7 @@ static int rtmp_http_read(URLContext *h, uint8_t *buf, int size) } else { off += ret; size -= ret; + rt->nb_bytes_read += ret; } } while (off <= 0); From 561687696f8a8764cabc64a482a2b72afc9d4a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 18 Jun 2012 23:39:30 +0300 Subject: [PATCH 02/19] network: Pass pointers of the right type to get/setsockopt/ioctlsocket on windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids warnings. Signed-off-by: Martin Storsjö --- libavformat/network.h | 2 ++ libavformat/os_support.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/network.h b/libavformat/network.h index 72d01d2986..1dc9deb675 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -35,6 +35,8 @@ #define ETIMEDOUT WSAETIMEDOUT #define ECONNREFUSED WSAECONNREFUSED #define EINPROGRESS WSAEINPROGRESS +#define getsockopt(a, b, c, d, e) getsockopt(a, b, c, (char*) d, e) +#define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (const char*) d, e) int ff_neterrno(void); #else diff --git a/libavformat/os_support.c b/libavformat/os_support.c index 889a005eeb..4181350b00 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -252,7 +252,8 @@ const char *ff_gai_strerror(int ecode) int ff_socket_nonblock(int socket, int enable) { #if HAVE_WINSOCK2_H - return ioctlsocket(socket, FIONBIO, &enable); + u_long param = enable; + return ioctlsocket(socket, FIONBIO, ¶m); #else if (enable) return fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK); From 6aa4e88106a554cef1d2294bb0a18b8f843032ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 19 Jun 2012 15:21:43 +0300 Subject: [PATCH 03/19] mmst: Use AVUNERROR() to convert error codes to the right range for strerror MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/mmst.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/mmst.c b/libavformat/mmst.c index 93ad073869..4b96f5d6af 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -144,7 +144,7 @@ static int send_command_packet(MMSTContext *mmst) av_log(NULL, AV_LOG_ERROR, "Failed to write data of length %d: %d (%s)\n", exact_length, write_result, - write_result < 0 ? strerror(write_result) : + write_result < 0 ? strerror(AVUNERROR(write_result)) : "The server closed the connection"); return AVERROR(EIO); } @@ -246,7 +246,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) if(read_result < 0) { av_log(NULL, AV_LOG_ERROR, "Error reading packet header: %d (%s)\n", - read_result, strerror(read_result)); + read_result, strerror(AVUNERROR(read_result))); packet_type = SC_PKT_CANCEL; } else { av_log(NULL, AV_LOG_ERROR, @@ -266,7 +266,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) av_log(NULL, AV_LOG_ERROR, "Reading command packet length failed: %d (%s)\n", read_result, - read_result < 0 ? strerror(read_result) : + read_result < 0 ? strerror(AVUNERROR(read_result)) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR(EIO); } @@ -287,7 +287,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) av_log(NULL, AV_LOG_ERROR, "Reading pkt data (length=%d) failed: %d (%s)\n", length_remaining, read_result, - read_result < 0 ? strerror(read_result) : + read_result < 0 ? strerror(AVUNERROR(read_result)) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR(EIO); } @@ -324,7 +324,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) av_log(NULL, AV_LOG_ERROR, "Failed to read packet data of size %d: %d (%s)\n", length_remaining, read_result, - read_result < 0 ? strerror(read_result) : + read_result < 0 ? strerror(AVUNERROR(read_result)) : "The server closed the connection"); return read_result < 0 ? read_result : AVERROR(EIO); } From 860b40f1f2f5ed2cda0f4a8f44a631ffd2f94482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 19 Jun 2012 15:28:48 +0300 Subject: [PATCH 04/19] udp: Properly print error from getnameinfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getnameinfo doesn't set errno on failure, it returns an error code, which should be handled by gai_strerror instead of the normal strerror. Signed-off-by: Martin Storsjö --- libavformat/udp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/udp.c b/libavformat/udp.c index 6571ab5d42..04433bc0af 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -218,9 +218,10 @@ static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, static int udp_port(struct sockaddr_storage *addr, int addr_len) { char sbuf[sizeof(int)*3+1]; + int error; - if (getnameinfo((struct sockaddr *)addr, addr_len, NULL, 0, sbuf, sizeof(sbuf), NI_NUMERICSERV) != 0) { - av_log(NULL, AV_LOG_ERROR, "getnameinfo: %s\n", strerror(errno)); + if ((error = getnameinfo((struct sockaddr *)addr, addr_len, NULL, 0, sbuf, sizeof(sbuf), NI_NUMERICSERV)) != 0) { + av_log(NULL, AV_LOG_ERROR, "getnameinfo: %s\n", gai_strerror(error)); return -1; } From a840cdda6cf7dbfe6858739f718d2ede9e3c375b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 19 Jun 2012 15:37:06 +0300 Subject: [PATCH 05/19] network: Use av_strerror for getting error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also use ff_neterrno() instead of errno directly (which doesn't work on windows), for getting the error code. Signed-off-by: Martin Storsjö --- libavformat/tcp.c | 6 ++++-- libavformat/udp.c | 31 +++++++++++++++++++------------ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 7e348f7729..e7c6210fc1 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -141,10 +141,12 @@ static int tcp_open(URLContext *h, const char *uri, int flags) optlen = sizeof(ret); getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); if (ret != 0) { + char errbuf[100]; + ret = AVERROR(ret); + av_strerror(ret, errbuf, sizeof(errbuf)); av_log(h, AV_LOG_ERROR, "TCP connection to %s:%d failed: %s\n", - hostname, port, strerror(ret)); - ret = AVERROR(ret); + hostname, port, errbuf); goto fail; } } diff --git a/libavformat/udp.c b/libavformat/udp.c index 04433bc0af..77ab8c27cf 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -57,13 +57,20 @@ typedef struct { #define UDP_TX_BUF_SIZE 32768 #define UDP_MAX_PKT_SIZE 65536 +static void log_net_error(void *ctx, int level, const char* prefix) +{ + char errbuf[100]; + av_strerror(ff_neterrno(), errbuf, sizeof(errbuf)); + av_log(ctx, level, "%s: %s\n", prefix, errbuf); +} + static int udp_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) { #ifdef IP_MULTICAST_TTL if (addr->sa_family == AF_INET) { if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) { - av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL): %s\n", strerror(errno)); + log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL)"); return -1; } } @@ -71,7 +78,7 @@ static int udp_set_multicast_ttl(int sockfd, int mcastTTL, #if defined(IPPROTO_IPV6) && defined(IPV6_MULTICAST_HOPS) if (addr->sa_family == AF_INET6) { if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) { - av_log(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS): %s\n", strerror(errno)); + log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS)"); return -1; } } @@ -88,7 +95,7 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr) mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; mreq.imr_interface.s_addr= INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { - av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP): %s\n", strerror(errno)); + log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP)"); return -1; } } @@ -100,7 +107,7 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr) memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); mreq6.ipv6mr_interface= 0; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { - av_log(NULL, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP): %s\n", strerror(errno)); + log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); return -1; } } @@ -117,7 +124,7 @@ static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr) mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; mreq.imr_interface.s_addr= INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { - av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP): %s\n", strerror(errno)); + log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP)"); return -1; } } @@ -129,7 +136,7 @@ static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr) memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); mreq6.ipv6mr_interface= 0; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { - av_log(NULL, AV_LOG_ERROR, "setsockopt(IPV6_DROP_MEMBERSHIP): %s\n", strerror(errno)); + log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_DROP_MEMBERSHIP)"); return -1; } } @@ -194,7 +201,7 @@ static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, for (res = res0; res; res=res->ai_next) { udp_fd = socket(res->ai_family, SOCK_DGRAM, 0); if (udp_fd > 0) break; - av_log(NULL, AV_LOG_ERROR, "socket: %s\n", strerror(errno)); + log_net_error(NULL, AV_LOG_ERROR, "socket"); } if (udp_fd < 0) @@ -268,7 +275,7 @@ int ff_udp_set_remote_url(URLContext *h, const char *uri) if (connect(s->udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) { s->is_connected = 0; - av_log(h, AV_LOG_ERROR, "connect: %s\n", strerror(errno)); + log_net_error(h, AV_LOG_ERROR, "connect"); return AVERROR(EIO); } } @@ -391,7 +398,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) * bind failed */ /* the bind is needed to give a port to the socket now */ if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) { - av_log(h, AV_LOG_ERROR, "bind failed: %s\n", strerror(errno)); + log_net_error(h, AV_LOG_ERROR, "bind failed"); goto fail; } @@ -416,7 +423,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) /* limit the tx buf size to limit latency */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) { - av_log(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF): %s\n", strerror(errno)); + log_net_error(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF)"); goto fail; } } else { @@ -424,14 +431,14 @@ static int udp_open(URLContext *h, const char *uri, int flags) * avoid losing data on OSes that set this too low by default. */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) { - av_log(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF): %s\n", strerror(errno)); + log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)"); } /* make the socket non-blocking */ ff_socket_nonblock(udp_fd, 1); } if (s->is_connected) { if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) { - av_log(h, AV_LOG_ERROR, "connect: %s\n", strerror(errno)); + log_net_error(h, AV_LOG_ERROR, "connect"); goto fail; } } From bb6c1abb0e022e1edaa5b3d8bb5abdff4f0c0ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 19 Jun 2012 17:50:38 +0300 Subject: [PATCH 06/19] tcp: Check the return value from getsockopt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we actually have an error code in ret, in case getsockopt failed. Signed-off-by: Martin Storsjö --- libavformat/tcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/tcp.c b/libavformat/tcp.c index e7c6210fc1..f1bad847d0 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -139,7 +139,8 @@ static int tcp_open(URLContext *h, const char *uri, int flags) } /* test error */ optlen = sizeof(ret); - getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); + if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) + ret = AVUNERROR(ff_neterrno()); if (ret != 0) { char errbuf[100]; ret = AVERROR(ret); From 042b272a4ad849c86d63ff1532beebc308d0ece9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 19 Jun 2012 17:59:57 +0300 Subject: [PATCH 07/19] udp: Properly check for invalid sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If stdin has been closed, 0 is a valid socket descriptor. Signed-off-by: Martin Storsjö --- libavformat/udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/udp.c b/libavformat/udp.c index 77ab8c27cf..0eaed1bfc8 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -200,7 +200,7 @@ static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, goto fail; for (res = res0; res; res=res->ai_next) { udp_fd = socket(res->ai_family, SOCK_DGRAM, 0); - if (udp_fd > 0) break; + if (udp_fd != -1) break; log_net_error(NULL, AV_LOG_ERROR, "socket"); } From 6bac8971cc6afc5deb3a60740c277e20f8191b95 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 19 Jun 2012 15:12:57 +0100 Subject: [PATCH 08/19] bfin: libswscale: remove unnecessary #includes Signed-off-by: Mans Rullgard --- libswscale/bfin/swscale_bfin.c | 11 ++--------- libswscale/bfin/yuv2rgb_bfin.c | 9 +-------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/libswscale/bfin/swscale_bfin.c b/libswscale/bfin/swscale_bfin.c index f9eba1e41b..7a85296c75 100644 --- a/libswscale/bfin/swscale_bfin.c +++ b/libswscale/bfin/swscale_bfin.c @@ -20,16 +20,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include -#include -#include -#include "config.h" -#include +#include -#include "libswscale/rgb2rgb.h" -#include "libswscale/swscale.h" +#include "config.h" #include "libswscale/swscale_internal.h" #if defined (__FDPIC__) && CONFIG_SRAM diff --git a/libswscale/bfin/yuv2rgb_bfin.c b/libswscale/bfin/yuv2rgb_bfin.c index 91a7aeea79..258bf8e9ac 100644 --- a/libswscale/bfin/yuv2rgb_bfin.c +++ b/libswscale/bfin/yuv2rgb_bfin.c @@ -21,16 +21,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include -#include -#include -#include +#include #include "config.h" -#include "libswscale/rgb2rgb.h" -#include "libswscale/swscale.h" #include "libswscale/swscale_internal.h" #if defined(__FDPIC__) && CONFIG_SRAM From 4996e8f510350ecbe9ca047a98d3b62eeb39adc5 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 19 Jun 2012 15:14:33 +0100 Subject: [PATCH 09/19] bfin: libswscale: add const where appropriate to fix warnings Signed-off-by: Mans Rullgard --- libswscale/bfin/swscale_bfin.c | 16 ++++++++-------- libswscale/bfin/yuv2rgb_bfin.c | 30 +++++++++++++++++------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/libswscale/bfin/swscale_bfin.c b/libswscale/bfin/swscale_bfin.c index 7a85296c75..f2fe871fc8 100644 --- a/libswscale/bfin/swscale_bfin.c +++ b/libswscale/bfin/swscale_bfin.c @@ -39,14 +39,14 @@ int ff_bfin_yuyvtoyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, int width, int height, int lumStride, int chromStride, int srcStride) L1CODE; -static int uyvytoyv12_unscaled(SwsContext *c, uint8_t *src[], int srcStride[], - int srcSliceY, int srcSliceH, uint8_t *dst[], - int dstStride[]) +static int uyvytoyv12_unscaled(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) { uint8_t *dsty = dst[0] + dstStride[0] * srcSliceY; uint8_t *dstu = dst[1] + dstStride[1] * srcSliceY / 2; uint8_t *dstv = dst[2] + dstStride[2] * srcSliceY / 2; - uint8_t *ip = src[0] + srcStride[0] * srcSliceY; + const uint8_t *ip = src[0] + srcStride[0] * srcSliceY; int w = dstStride[0]; ff_bfin_uyvytoyv12(ip, dsty, dstu, dstv, w, srcSliceH, @@ -55,14 +55,14 @@ static int uyvytoyv12_unscaled(SwsContext *c, uint8_t *src[], int srcStride[], return srcSliceH; } -static int yuyvtoyv12_unscaled(SwsContext *c, uint8_t *src[], int srcStride[], - int srcSliceY, int srcSliceH, uint8_t *dst[], - int dstStride[]) +static int yuyvtoyv12_unscaled(SwsContext *c, const uint8_t *src[], + int srcStride[], int srcSliceY, int srcSliceH, + uint8_t *dst[], int dstStride[]) { uint8_t *dsty = dst[0] + dstStride[0] * srcSliceY; uint8_t *dstu = dst[1] + dstStride[1] * srcSliceY / 2; uint8_t *dstv = dst[2] + dstStride[2] * srcSliceY / 2; - uint8_t *ip = src[0] + srcStride[0] * srcSliceY; + const uint8_t *ip = src[0] + srcStride[0] * srcSliceY; int w = dstStride[0]; ff_bfin_yuyvtoyv12(ip, dsty, dstu, dstv, w, srcSliceH, diff --git a/libswscale/bfin/yuv2rgb_bfin.c b/libswscale/bfin/yuv2rgb_bfin.c index 258bf8e9ac..4078a18660 100644 --- a/libswscale/bfin/yuv2rgb_bfin.c +++ b/libswscale/bfin/yuv2rgb_bfin.c @@ -32,17 +32,20 @@ #define L1CODE #endif -void ff_bfin_yuv2rgb555_line(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, +void ff_bfin_yuv2rgb555_line(const uint8_t *Y, const uint8_t *U, + const uint8_t *V, uint8_t *out, int w, uint32_t *coeffs) L1CODE; -void ff_bfin_yuv2rgb565_line(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, +void ff_bfin_yuv2rgb565_line(const uint8_t *Y, const uint8_t *U, + const uint8_t *V, uint8_t *out, int w, uint32_t *coeffs) L1CODE; -void ff_bfin_yuv2rgb24_line(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, +void ff_bfin_yuv2rgb24_line(const uint8_t *Y, const uint8_t *U, + const uint8_t *V, uint8_t *out, int w, uint32_t *coeffs) L1CODE; -typedef void (*ltransform)(uint8_t *Y, uint8_t *U, uint8_t *V, uint8_t *out, - int w, uint32_t *coeffs); +typedef void (*ltransform)(const uint8_t *Y, const uint8_t *U, const uint8_t *V, + uint8_t *out, int w, uint32_t *coeffs); static void bfin_prepare_coefficients(SwsContext *c, int rgb, int masks) { @@ -80,12 +83,13 @@ static void bfin_prepare_coefficients(SwsContext *c, int rgb, int masks) } } -static int core_yuv420_rgb(SwsContext *c, uint8_t **in, int *instrides, +static int core_yuv420_rgb(SwsContext *c, const uint8_t **in, int *instrides, int srcSliceY, int srcSliceH, uint8_t **oplanes, int *outstrides, ltransform lcscf, int rgb, int masks) { - uint8_t *py, *pu, *pv, *op; + const uint8_t *py, *pu, *pv; + uint8_t *op; int w = instrides[0]; int h2 = srcSliceH >> 1; int i; @@ -115,7 +119,7 @@ static int core_yuv420_rgb(SwsContext *c, uint8_t **in, int *instrides, return srcSliceH; } -static int bfin_yuv420_rgb555(SwsContext *c, uint8_t **in, int *instrides, +static int bfin_yuv420_rgb555(SwsContext *c, const uint8_t **in, int *instrides, int srcSliceY, int srcSliceH, uint8_t **oplanes, int *outstrides) { @@ -123,7 +127,7 @@ static int bfin_yuv420_rgb555(SwsContext *c, uint8_t **in, int *instrides, outstrides, ff_bfin_yuv2rgb555_line, 1, 555); } -static int bfin_yuv420_bgr555(SwsContext *c, uint8_t **in, int *instrides, +static int bfin_yuv420_bgr555(SwsContext *c, const uint8_t **in, int *instrides, int srcSliceY, int srcSliceH, uint8_t **oplanes, int *outstrides) { @@ -131,7 +135,7 @@ static int bfin_yuv420_bgr555(SwsContext *c, uint8_t **in, int *instrides, outstrides, ff_bfin_yuv2rgb555_line, 0, 555); } -static int bfin_yuv420_rgb24(SwsContext *c, uint8_t **in, int *instrides, +static int bfin_yuv420_rgb24(SwsContext *c, const uint8_t **in, int *instrides, int srcSliceY, int srcSliceH, uint8_t **oplanes, int *outstrides) { @@ -139,7 +143,7 @@ static int bfin_yuv420_rgb24(SwsContext *c, uint8_t **in, int *instrides, outstrides, ff_bfin_yuv2rgb24_line, 1, 888); } -static int bfin_yuv420_bgr24(SwsContext *c, uint8_t **in, int *instrides, +static int bfin_yuv420_bgr24(SwsContext *c, const uint8_t **in, int *instrides, int srcSliceY, int srcSliceH, uint8_t **oplanes, int *outstrides) { @@ -147,7 +151,7 @@ static int bfin_yuv420_bgr24(SwsContext *c, uint8_t **in, int *instrides, outstrides, ff_bfin_yuv2rgb24_line, 0, 888); } -static int bfin_yuv420_rgb565(SwsContext *c, uint8_t **in, int *instrides, +static int bfin_yuv420_rgb565(SwsContext *c, const uint8_t **in, int *instrides, int srcSliceY, int srcSliceH, uint8_t **oplanes, int *outstrides) { @@ -155,7 +159,7 @@ static int bfin_yuv420_rgb565(SwsContext *c, uint8_t **in, int *instrides, outstrides, ff_bfin_yuv2rgb565_line, 1, 565); } -static int bfin_yuv420_bgr565(SwsContext *c, uint8_t **in, int *instrides, +static int bfin_yuv420_bgr565(SwsContext *c, const uint8_t **in, int *instrides, int srcSliceY, int srcSliceH, uint8_t **oplanes, int *outstrides) { From 4e5a51481343ef4e08a3779186f466f3458259ff Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 19 Jun 2012 15:11:34 +0100 Subject: [PATCH 10/19] lavf: remove unnecessary inclusions of unistd.h These files do not use anything provided by unistd.h. Signed-off-by: Mans Rullgard --- libavformat/http.c | 1 - libavformat/os_support.c | 1 - libavformat/rtpdec_h264.c | 1 - libavformat/rtpproto.c | 1 - 4 files changed, 4 deletions(-) diff --git a/libavformat/http.c b/libavformat/http.c index 8ccb64986c..ce4a508eba 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -21,7 +21,6 @@ #include "libavutil/avstring.h" #include "avformat.h" -#include #include "internal.h" #include "network.h" #include "http.h" diff --git a/libavformat/os_support.c b/libavformat/os_support.c index 4181350b00..eaada4be0b 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -57,7 +57,6 @@ int ff_win32_open(const char *filename_utf8, int oflag, int pmode) #if CONFIG_NETWORK #include -#include #if !HAVE_POLL_H #include #if HAVE_WINSOCK2_H diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c index 829053a69d..c192d976c1 100644 --- a/libavformat/rtpdec_h264.c +++ b/libavformat/rtpdec_h264.c @@ -39,7 +39,6 @@ #include "avformat.h" #include "mpegts.h" -#include #include "network.h" #include diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index c93de4af2b..881a188161 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -31,7 +31,6 @@ #include "rtpdec.h" #include "url.h" -#include #include #include "internal.h" #include "network.h" From 6501dcfb5e3797b66f63de030fabe774b5f4596f Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Tue, 19 Jun 2012 22:08:35 +0100 Subject: [PATCH 11/19] Remove unnecessary inclusions of [sys/]time.h Signed-off-by: Mans Rullgard --- avconv.c | 1 - avserver.c | 1 - libavdevice/dv1394.c | 2 -- libavdevice/fbdev.c | 1 - libavdevice/oss_audio.c | 2 -- libavdevice/v4l2.c | 1 - libavformat/rtpproto.c | 1 - libavformat/rtsp.c | 1 - libavformat/rtspenc.c | 1 - libavformat/sapdec.c | 1 - libavformat/sctp.c | 1 - libavformat/tcp.c | 1 - libavformat/udp.c | 1 - libavutil/parseutils.c | 1 - 14 files changed, 16 deletions(-) diff --git a/avconv.c b/avconv.c index 9da8d8aeca..7abf10d7b0 100644 --- a/avconv.c +++ b/avconv.c @@ -55,7 +55,6 @@ #if HAVE_SYS_RESOURCE_H #include -#include #include #elif HAVE_GETPROCESSTIMES #include diff --git a/avserver.c b/avserver.c index 5777a08cd3..60509652cd 100644 --- a/avserver.c +++ b/avserver.c @@ -51,7 +51,6 @@ #include #endif #include -#include #include #include #include diff --git a/libavdevice/dv1394.c b/libavdevice/dv1394.c index f48d2b1506..2bb65b6a38 100644 --- a/libavdevice/dv1394.c +++ b/libavdevice/dv1394.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include "libavutil/log.h" #include "libavutil/opt.h" diff --git a/libavdevice/fbdev.c b/libavdevice/fbdev.c index f79893a6d4..d789d41afa 100644 --- a/libavdevice/fbdev.c +++ b/libavdevice/fbdev.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/libavdevice/oss_audio.c b/libavdevice/oss_audio.c index e592c32849..60432c5fc5 100644 --- a/libavdevice/oss_audio.c +++ b/libavdevice/oss_audio.c @@ -33,8 +33,6 @@ #include #include #include -#include -#include #include "libavutil/log.h" #include "libavutil/opt.h" diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index b9941d212c..2154b63aa2 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -42,7 +42,6 @@ #else #include #endif -#include #include "libavutil/imgutils.h" #include "libavutil/log.h" #include "libavutil/opt.h" diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 881a188161..e70b89ec9e 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -39,7 +39,6 @@ #if HAVE_POLL_H #include #endif -#include #define RTP_TX_BUF_SIZE (64 * 1024) #define RTP_RX_BUF_SIZE (128 * 1024) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index a70ea04df2..76b5df8400 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -30,7 +30,6 @@ #include "avformat.h" #include "avio_internal.h" -#include #if HAVE_POLL_H #include #endif diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index ad6e485906..c7fb2fa9d9 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -21,7 +21,6 @@ #include "avformat.h" -#include #if HAVE_POLL_H #include #endif diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c index 46a4b96b93..e377cefda9 100644 --- a/libavformat/sapdec.c +++ b/libavformat/sapdec.c @@ -30,7 +30,6 @@ #if HAVE_POLL_H #include #endif -#include struct SAPState { URLContext *ann_fd; diff --git a/libavformat/sctp.c b/libavformat/sctp.c index 817b0049a9..07de4986d2 100644 --- a/libavformat/sctp.c +++ b/libavformat/sctp.c @@ -39,7 +39,6 @@ #include #include -#include #include #include "config.h" diff --git a/libavformat/tcp.c b/libavformat/tcp.c index f1bad847d0..e77e4c5231 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -28,7 +28,6 @@ #if HAVE_POLL_H #include #endif -#include typedef struct TCPContext { int fd; diff --git a/libavformat/udp.c b/libavformat/udp.c index 0eaed1bfc8..39db263e12 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -35,7 +35,6 @@ #include "network.h" #include "os_support.h" #include "url.h" -#include #ifndef IPV6_ADD_MEMBERSHIP #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index ed147eef3d..34f45eb2d1 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -21,7 +21,6 @@ * misc parsing utilities */ -#include #include #include "avstring.h" From a2b186a188c126dd0402414d9e8198ec4df63ebe Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 14 Jun 2012 20:13:00 +0200 Subject: [PATCH 12/19] mathematics.h: remove a couple of math defines While these defines are not defined by the C standard they are standardized as X/Open System Interfaces Extension. We use the appropiate _XOPEN_SOURCE define to make them available. They seem to be available on all FATE configs since the constants are used in files where mathematics.h is not included. --- libavutil/mathematics.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index ec27979bc9..a734b75c02 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -26,30 +26,12 @@ #include "attributes.h" #include "rational.h" -#ifndef M_E -#define M_E 2.7182818284590452354 /* e */ -#endif -#ifndef M_LN2 -#define M_LN2 0.69314718055994530942 /* log_e 2 */ -#endif -#ifndef M_LN10 -#define M_LN10 2.30258509299404568402 /* log_e 10 */ -#endif #ifndef M_LOG2_10 #define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ #endif #ifndef M_PHI #define M_PHI 1.61803398874989484820 /* phi / golden ratio */ #endif -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ -#endif -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ -#endif #ifndef NAN #define NAN (0.0/0.0) #endif From f1f37c701143003fe5506a1fca971932382188ce Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 18 Jun 2012 20:06:35 +0100 Subject: [PATCH 13/19] mov: fix operator precedence bug --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 44dc2c821c..63c79cd002 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1024,7 +1024,7 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_INVALIDDATA; profile_level = avio_r8(pb); - if (profile_level & 0xf0 != 0xc0) + if ((profile_level & 0xf0) != 0xc0) return 0; av_free(st->codec->extradata); From db7d8fb4ef950329745224d49c8d4fb4174baa22 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 20 Jun 2012 13:50:45 +0100 Subject: [PATCH 14/19] dct-test: use emms_c() from libavutil instead of duplicating it --- libavcodec/dct-test.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index bc5f2c5aaa..d57789395f 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -181,14 +181,6 @@ static void idct_mmx_init(void) DECLARE_ALIGNED(16, static DCTELEM, block)[64]; DECLARE_ALIGNED(8, static DCTELEM, block1)[64]; -static inline void mmx_emms(void) -{ -#if HAVE_MMX - if (cpu_flags & AV_CPU_FLAG_MMX) - __asm__ volatile ("emms\n\t"); -#endif -} - static void init_block(DCTELEM block[64], int test, int is_idct, AVLFG *prng) { int i, j; @@ -263,7 +255,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) permute(block, block1, dct->format); dct->func(block); - mmx_emms(); + emms_c(); if (dct->format == SCALE_PERM) { for (i = 0; i < 64; i++) { @@ -330,7 +322,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) it1 += NB_ITS_SPEED; ti1 = gettime() - ti; } while (ti1 < 1000000); - mmx_emms(); + emms_c(); printf("%s %s: %0.1f kdct/s\n", is_idct ? "IDCT" : "DCT", dct->name, (double) it1 * 1000.0 / (double) ti1); @@ -472,7 +464,7 @@ static void idct248_error(const char *name, it1 += NB_ITS_SPEED; ti1 = gettime() - ti; } while (ti1 < 1000000); - mmx_emms(); + emms_c(); printf("%s %s: %0.1f kdct/s\n", 1 ? "IDCT248" : "DCT248", name, (double) it1 * 1000.0 / (double) ti1); From ae0a301668da542eaf8855e5dd61d0728181b0dd Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 20 Jun 2012 01:24:39 +0100 Subject: [PATCH 15/19] Move av_gettime() to libavutil Signed-off-by: Mans Rullgard --- libavformat/avformat.h | 5 ++--- libavformat/utils.c | 10 ++++------ libavformat/version.h | 3 +++ libavutil/Makefile | 2 ++ libavutil/time.c | 30 ++++++++++++++++++++++++++++++ libavutil/time.h | 29 +++++++++++++++++++++++++++++ 6 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 libavutil/time.c create mode 100644 libavutil/time.h diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 040e35eb92..1c1aad652f 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1635,10 +1635,9 @@ void av_dump_format(AVFormatContext *ic, const char *url, int is_output); -/** - * Get the current time in microseconds. - */ +#if FF_API_AV_GETTIME int64_t av_gettime(void); +#endif /** * Return in 'buf' the path with '%d' replaced by a number. diff --git a/libavformat/utils.c b/libavformat/utils.c index 5450dc4bff..156c527e25 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -38,8 +38,6 @@ #include "riff.h" #include "audiointerleave.h" #include "url.h" -#include -#include #include #if CONFIG_NETWORK #include "network.h" @@ -3411,12 +3409,12 @@ void av_dump_format(AVFormatContext *ic, av_free(printed); } -int64_t av_gettime(void) +#if FF_API_AV_GETTIME && CONFIG_SHARED && HAVE_SYMVER +FF_SYMVER(int64_t, av_gettime, (void), "LIBAVFORMAT_54") { - struct timeval tv; - gettimeofday(&tv,NULL); - return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; + return av_gettime(); } +#endif uint64_t ff_ntp_time(void) { diff --git a/libavformat/version.h b/libavformat/version.h index 2216e4eabd..29e520534c 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -59,5 +59,8 @@ #ifndef FF_API_INTERLEAVE_PACKET #define FF_API_INTERLEAVE_PACKET (LIBAVFORMAT_VERSION_MAJOR < 55) #endif +#ifndef FF_API_AV_GETTIME +#define FF_API_AV_GETTIME (LIBAVFORMAT_VERSION_MAJOR < 55) +#endif #endif /* AVFORMAT_VERSION_H */ diff --git a/libavutil/Makefile b/libavutil/Makefile index 56ccd04dff..6fe174bb62 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -36,6 +36,7 @@ HEADERS = adler32.h \ rational.h \ samplefmt.h \ sha.h \ + time.h \ ARCH_HEADERS = bswap.h \ intmath.h \ @@ -77,6 +78,7 @@ OBJS = adler32.o \ rc4.o \ samplefmt.o \ sha.o \ + time.o \ tree.o \ utils.o \ diff --git a/libavutil/time.c b/libavutil/time.c new file mode 100644 index 0000000000..a0b713e803 --- /dev/null +++ b/libavutil/time.c @@ -0,0 +1,30 @@ +/* + * 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 + */ + +#include +#include +#include + +#include "libavutil/time.h" + +int64_t av_gettime(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; +} diff --git a/libavutil/time.h b/libavutil/time.h new file mode 100644 index 0000000000..2ee7e08caf --- /dev/null +++ b/libavutil/time.h @@ -0,0 +1,29 @@ +/* + * 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 + */ + +#ifndef AVUTIL_TIME_H +#define AVUTIL_TIME_H + +#include + +/** + * Get the current time in microseconds. + */ +int64_t av_gettime(void); + +#endif /* AVUTIL_TIME_H */ From 980f81d961e62dd38b9dbe6091e72638d6535ccd Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 20 Jun 2012 01:34:38 +0100 Subject: [PATCH 16/19] Use av_gettime() in various places Signed-off-by: Mans Rullgard --- libavcodec/dct-test.c | 17 +++++------------ libavcodec/fft-test.c | 13 +++---------- libavcodec/motion-test.c | 12 +++--------- libavutil/des.c | 6 ++---- 4 files changed, 13 insertions(+), 35 deletions(-) diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index d57789395f..4647642080 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -28,13 +28,13 @@ #include #include #include -#include #include #include #include "libavutil/cpu.h" #include "libavutil/common.h" #include "libavutil/lfg.h" +#include "libavutil/time.h" #include "simple_idct.h" #include "aandcttab.h" @@ -143,13 +143,6 @@ static const struct algo idct_tab[] = { #define AANSCALE_BITS 12 -static int64_t gettime(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; -} - #define NB_ITS 20000 #define NB_ITS_SPEED 50000 @@ -312,7 +305,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) init_block(block, test, is_idct, &prng); permute(block1, block, dct->format); - ti = gettime(); + ti = av_gettime(); it1 = 0; do { for (it = 0; it < NB_ITS_SPEED; it++) { @@ -320,7 +313,7 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) dct->func(block); } it1 += NB_ITS_SPEED; - ti1 = gettime() - ti; + ti1 = av_gettime() - ti; } while (ti1 < 1000000); emms_c(); @@ -453,7 +446,7 @@ static void idct248_error(const char *name, if (!speed) return; - ti = gettime(); + ti = av_gettime(); it1 = 0; do { for (it = 0; it < NB_ITS_SPEED; it++) { @@ -462,7 +455,7 @@ static void idct248_error(const char *name, idct248_put(img_dest, 8, block); } it1 += NB_ITS_SPEED; - ti1 = gettime() - ti; + ti1 = av_gettime() - ti; } while (ti1 < 1000000); emms_c(); diff --git a/libavcodec/fft-test.c b/libavcodec/fft-test.c index 70c0655ad0..75941a1071 100644 --- a/libavcodec/fft-test.c +++ b/libavcodec/fft-test.c @@ -27,6 +27,7 @@ #include "libavutil/mathematics.h" #include "libavutil/lfg.h" #include "libavutil/log.h" +#include "libavutil/time.h" #include "fft.h" #if CONFIG_FFT_FLOAT #include "dct.h" @@ -34,7 +35,6 @@ #endif #include #include -#include #include #include @@ -186,13 +186,6 @@ static FFTSample frandom(AVLFG *prng) return (int16_t)av_lfg_get(prng) / 32768.0 * RANGE; } -static int64_t gettime(void) -{ - struct timeval tv; - gettimeofday(&tv,NULL); - return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; -} - static int check_diff(FFTSample *tab1, FFTSample *tab2, int n, double scale) { int i; @@ -430,7 +423,7 @@ int main(int argc, char **argv) /* we measure during about 1 seconds */ nb_its = 1; for(;;) { - time_start = gettime(); + time_start = av_gettime(); for (it = 0; it < nb_its; it++) { switch (transform) { case TRANSFORM_MDCT: @@ -456,7 +449,7 @@ int main(int argc, char **argv) #endif } } - duration = gettime() - time_start; + duration = av_gettime() - time_start; if (duration >= 1000000) break; nb_its *= 2; diff --git a/libavcodec/motion-test.c b/libavcodec/motion-test.c index fb97f085be..bf63182db1 100644 --- a/libavcodec/motion-test.c +++ b/libavcodec/motion-test.c @@ -32,6 +32,7 @@ #include "config.h" #include "dsputil.h" #include "libavutil/lfg.h" +#include "libavutil/time.h" #undef printf @@ -58,13 +59,6 @@ static void help(void) "test motion implementations\n"); } -static int64_t gettime(void) -{ - struct timeval tv; - gettimeofday(&tv,NULL); - return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; -} - #define NB_ITS 500 int dummy; @@ -97,7 +91,7 @@ static void test_motion(const char *name, emms_c(); /* speed test */ - ti = gettime(); + ti = av_gettime(); d1 = 0; for(it=0;it #include -#include +#include "libavutil/time.h" static uint64_t rand64(void) { uint64_t r = rand(); r = (r << 32) | rand(); @@ -389,13 +389,11 @@ int main(void) { #ifdef GENTABLES int j; #endif - struct timeval tv; uint64_t key[3]; uint64_t data; uint64_t ct; uint64_t roundkeys[16]; - gettimeofday(&tv, NULL); - srand(tv.tv_sec * 1000 * 1000 + tv.tv_usec); + srand(av_gettime()); key[0] = AV_RB64(test_key); data = AV_RB64(plain); gen_roundkeys(roundkeys, key[0]); From 61183b5ab4c203363ee0ee696bdf4819be307230 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 20 Jun 2012 13:46:52 +0100 Subject: [PATCH 17/19] av_gettime: support Win32 without gettimeofday() Based on patch by Ronald S. Bultje. Signed-off-by: Mans Rullgard --- configure | 4 ++++ libavutil/time.c | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/configure b/configure index 0baa755d77..07608c4df3 100755 --- a/configure +++ b/configure @@ -1084,7 +1084,9 @@ HAVE_LIST=" GetProcessAffinityMask GetProcessMemoryInfo GetProcessTimes + GetSystemTimeAsFileTime getrusage + gettimeofday gnu_as ibm_asm inet_aton @@ -2832,6 +2834,7 @@ check_func getaddrinfo $network_extralibs check_func gethrtime check_func getrusage check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss +check_func gettimeofday check_func inet_aton $network_extralibs check_func isatty check_func localtime_r @@ -2851,6 +2854,7 @@ check_func_headers io.h setmode check_lib2 "windows.h psapi.h" GetProcessMemoryInfo -lpsapi check_func_headers windows.h GetProcessAffinityMask check_func_headers windows.h GetProcessTimes +check_func_headers windows.h GetSystemTimeAsFileTime check_func_headers windows.h MapViewOfFile check_func_headers windows.h VirtualAlloc diff --git a/libavutil/time.c b/libavutil/time.c index a0b713e803..80c4029d9b 100644 --- a/libavutil/time.c +++ b/libavutil/time.c @@ -16,15 +16,31 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include #include +#if HAVE_GETTIMEOFDAY #include +#elif HAVE_GETSYSTEMTIMEASFILETIME +#include +#endif #include "libavutil/time.h" int64_t av_gettime(void) { +#if HAVE_GETTIMEOFDAY struct timeval tv; gettimeofday(&tv, NULL); return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; +#elif HAVE_GETSYSTEMTIMEASFILETIME + FILETIME ft; + int64_t t; + GetSystemTimeAsFileTime(&ft); + t = (int64_t)ft.dwHighDateTime << 32 | ft.dwLowDateTime; + return t / 10 - 11644473600000000; /* Jan 1, 1601 */ +#else + return -1; +#endif } From 43886eaebc8e803a2f90051afd03068be47e398f Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Tue, 19 Jun 2012 19:06:34 -0700 Subject: [PATCH 18/19] aacdec: Fix popping channel layouts. 'channel_layout' not 'channels' from the stored configuration should go to AVCodecContext's 'channel_layout'. --- libavcodec/aacdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 3cf4a7fe18..f16b831ccd 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -368,7 +368,7 @@ static void pop_output_configuration(AACContext *ac) { if (ac->oc[1].status != OC_LOCKED) { ac->oc[1] = ac->oc[0]; ac->avctx->channels = ac->oc[1].channels; - ac->avctx->channel_layout = ac->oc[1].channels; + ac->avctx->channel_layout = ac->oc[1].channel_layout; } } From 005c80b645cc6ab5f30cbc3e10ab66a15dfd107e Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Fri, 15 Jun 2012 20:37:37 +0200 Subject: [PATCH 19/19] MS Screen 1 decoder --- Changelog | 1 + doc/general.texi | 2 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/mss1.c | 845 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavformat/riff.c | 1 + 8 files changed, 853 insertions(+), 1 deletion(-) create mode 100644 libavcodec/mss1.c diff --git a/Changelog b/Changelog index 51b8c83764..8ee9b8f30a 100644 --- a/Changelog +++ b/Changelog @@ -27,6 +27,7 @@ version : - channelsplit audio filter - RTMPT protocol support - iLBC encoding/decoding via libilbc +- Microsoft Screen 1 decoder version 0.8: diff --git a/doc/general.texi b/doc/general.texi index 82a181c822..28e89f0d78 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -532,6 +532,8 @@ following image formats are supported: @item LOCO @tab @tab X @item lossless MJPEG @tab X @tab X @item Microsoft RLE @tab @tab X +@item Microsoft Screen 1 @tab @tab X + @tab Also known as Windows Media Video V7 Screen. @item Microsoft Video 1 @tab @tab X @item Mimic @tab @tab X @tab Used in MSN Messenger Webcam streams. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index c4f7e986fa..8204a1848d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -292,6 +292,7 @@ OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4.o msmpeg4enc.o msmpeg4data.o \ h263dec.o h263.o ituh263dec.o \ mpeg4videodec.o OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o +OBJS-$(CONFIG_MSS1_DECODER) += mss1.o OBJS-$(CONFIG_MSVIDEO1_DECODER) += msvideo1.o OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o mjpegdec.o mjpeg.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index a9d85e694f..f6a2df8a94 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -156,6 +156,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (MSMPEG4V2, msmpeg4v2); REGISTER_ENCDEC (MSMPEG4V3, msmpeg4v3); REGISTER_DECODER (MSRLE, msrle); + REGISTER_DECODER (MSS1, mss1); REGISTER_DECODER (MSVIDEO1, msvideo1); REGISTER_DECODER (MSZH, mszh); REGISTER_DECODER (MXPEG, mxpeg); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index eac68946b2..5ba021c873 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -255,6 +255,7 @@ enum CodecID { CODEC_ID_CDXL, CODEC_ID_XBM, CODEC_ID_ZEROCODEC, + CODEC_ID_MSS1, /* various PCM "codecs" */ CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c new file mode 100644 index 0000000000..952737440b --- /dev/null +++ b/libavcodec/mss1.c @@ -0,0 +1,845 @@ +/* + * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder + */ + +#include "libavutil/intfloat.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "get_bits.h" + +enum SplitMode { + SPLIT_VERT = 0, + SPLIT_HOR, + SPLIT_NONE +}; + +typedef struct ArithCoder { + int low, high, value; + GetBitContext *gb; +} ArithCoder; + +#define MODEL_MIN_SYMS 2 +#define MODEL_MAX_SYMS 256 +#define THRESH_ADAPTIVE -1 +#define THRESH_LOW 15 +#define THRESH_HIGH 50 + +typedef struct Model { + int cum_prob[MODEL_MAX_SYMS + 1]; + int weights[MODEL_MAX_SYMS + 1]; + int idx2sym[MODEL_MAX_SYMS + 1]; + int sym2idx[MODEL_MAX_SYMS + 1]; + int num_syms; + int thr_weight, threshold; +} Model; + +static const int sec_order_sizes[4] = { 1, 7, 6, 1 }; + +enum ContextDirection { + TOP_LEFT = 0, + TOP, + TOP_RIGHT, + LEFT +}; + +typedef struct PixContext { + int cache_size, num_syms; + uint8_t cache[12]; + Model cache_model, full_model; + Model sec_models[4][8][4]; +} PixContext; + +typedef struct MSS1Context { + AVCodecContext *avctx; + AVFrame pic; + uint8_t *pic_start; + int pic_stride; + uint8_t *mask; + int mask_linesize; + uint32_t pal[256]; + int free_colours; + Model intra_region, inter_region; + Model pivot, edge_mode, split_mode; + PixContext intra_pix_ctx, inter_pix_ctx; + int corrupted; +} MSS1Context; + +static void arith_init(ArithCoder *c, GetBitContext *gb) +{ + c->low = 0; + c->high = 0xFFFF; + c->value = get_bits(gb, 16); + c->gb = gb; +} + +static void arith_normalise(ArithCoder *c) +{ + for (;;) { + if (c->high >= 0x8000) { + if (c->low < 0x8000) { + if (c->low >= 0x4000 && c->high < 0xC000) { + c->value -= 0x4000; + c->low -= 0x4000; + c->high -= 0x4000; + } else { + return; + } + } else { + c->value -= 0x8000; + c->low -= 0x8000; + c->high -= 0x8000; + } + } + c->value <<= 1; + c->low <<= 1; + c->high <<= 1; + c->high |= 1; + c->value |= get_bits1(c->gb); + } +} + +static int arith_get_bit(ArithCoder *c) +{ + int range = c->high - c->low + 1; + int bit = (((c->value - c->low) << 1) + 1) / range; + + if (bit) + c->low += range >> 1; + else + c->high = c->low + (range >> 1) - 1; + + arith_normalise(c); + + return bit; +} + +static int arith_get_bits(ArithCoder *c, int bits) +{ + int range = c->high - c->low + 1; + int val = (((c->value - c->low + 1) << bits) - 1) / range; + int prob = range * val; + + c->high = ((prob + range) >> bits) + c->low - 1; + c->low += prob >> bits; + + arith_normalise(c); + + return val; +} + +static int arith_get_number(ArithCoder *c, int mod_val) +{ + int range = c->high - c->low + 1; + int val = ((c->value - c->low + 1) * mod_val - 1) / range; + int prob = range * val; + + c->high = (prob + range) / mod_val + c->low - 1; + c->low += prob / mod_val; + + arith_normalise(c); + + return val; +} + +static int arith_get_prob(ArithCoder *c, int *probs) +{ + int range = c->high - c->low + 1; + int val = ((c->value - c->low + 1) * probs[0] - 1) / range; + int sym = 1; + + while (probs[sym] > val) + sym++; + + c->high = range * probs[sym - 1] / probs[0] + c->low - 1; + c->low += range * probs[sym] / probs[0]; + + return sym; +} + +static int model_calc_threshold(Model *m) +{ + int thr; + + if (m->thr_weight == -1) { + thr = 2 * m->weights[m->num_syms] - 1; + thr = ((thr >> 1) + 4 * m->cum_prob[0]) / thr; + } else { + thr = m->num_syms * m->thr_weight; + } + + return FFMIN(thr, 0x3FFF); +} + +static void model_reset(Model *m) +{ + int i; + + for (i = 0; i <= m->num_syms; i++) { + m->weights[i] = 1; + m->cum_prob[i] = m->num_syms - i; + } + m->weights[0] = -1; + m->idx2sym[0] = -1; + m->sym2idx[m->num_syms] = -1; + for (i = 0; i < m->num_syms; i++) { + m->sym2idx[i] = i + 1; + m->idx2sym[i + 1] = i; + } +} + +static av_cold void model_init(Model *m, int num_syms, int thr_weight) +{ + m->num_syms = num_syms; + m->thr_weight = thr_weight; + m->threshold = model_calc_threshold(m); + model_reset(m); +} + +static void model_rescale_weights(Model *m) +{ + int i; + int cum_prob; + + if (m->thr_weight == -1) + m->threshold = model_calc_threshold(m); + while (m->cum_prob[0] > m->threshold) { + cum_prob = 0; + for (i = m->num_syms; i >= 0; i--) { + m->cum_prob[i] = cum_prob; + m->weights[i] = (m->weights[i] + 1) >> 1; + cum_prob += m->weights[i]; + } + } +} + +static void model_update(Model *m, int val) +{ + int i; + + if (m->weights[val] == m->weights[val - 1]) { + for (i = val; m->weights[i - 1] == m->weights[val]; i--); + if (i != val) { + int sym1, sym2; + + sym1 = m->idx2sym[val]; + sym2 = m->idx2sym[i]; + + m->idx2sym[val] = sym2; + m->idx2sym[i] = sym1; + m->sym2idx[sym1] = i; + m->sym2idx[sym2] = val; + + val = i; + } + } + m->weights[val]++; + for (i = val - 1; i >= 0; i--) + m->cum_prob[i]++; + model_rescale_weights(m); +} + +static int arith_get_model_sym(ArithCoder *c, Model *m) +{ + int idx, val; + + idx = arith_get_prob(c, m->cum_prob); + + val = m->idx2sym[idx]; + model_update(m, idx); + + arith_normalise(c); + + return val; +} + +static void pixctx_reset(PixContext *ctx) +{ + int i, j, k; + + for (i = 0; i < ctx->cache_size; i++) + ctx->cache[i] = i; + + model_reset(&ctx->cache_model); + model_reset(&ctx->full_model); + + for (i = 0; i < 4; i++) + for (j = 0; j < sec_order_sizes[i]; j++) + for (k = 0; k < 4; k++) + model_reset(&ctx->sec_models[i][j][k]); +} + +static av_cold void pixctx_init(PixContext *ctx, int cache_size) +{ + int i, j, k; + + ctx->cache_size = cache_size + 4; + ctx->num_syms = cache_size; + + for (i = 0; i < ctx->cache_size; i++) + ctx->cache[i] = i; + + model_init(&ctx->cache_model, ctx->num_syms + 1, THRESH_LOW); + model_init(&ctx->full_model, 256, THRESH_HIGH); + + for (i = 0; i < 4; i++) { + for (j = 0; j < sec_order_sizes[i]; j++) { + for (k = 0; k < 4; k++) { + model_init(&ctx->sec_models[i][j][k], 2 + i, + i ? THRESH_LOW : THRESH_ADAPTIVE); + } + } + } +} + +static int decode_top_left_pixel(ArithCoder *acoder, PixContext *pctx) +{ + int i, val, pix; + + val = arith_get_model_sym(acoder, &pctx->cache_model); + if (val < pctx->num_syms) { + pix = pctx->cache[val]; + } else { + pix = arith_get_model_sym(acoder, &pctx->full_model); + for (i = 0; i < pctx->cache_size - 1; i++) + if (pctx->cache[i] == pix) + break; + val = i; + } + if (val) { + for (i = val; i > 0; i--) + pctx->cache[i] = pctx->cache[i - 1]; + pctx->cache[0] = pix; + } + + return pix; +} + +static int decode_pixel(ArithCoder *acoder, PixContext *pctx, + uint8_t *ngb, int num_ngb) +{ + int i, val, pix; + + val = arith_get_model_sym(acoder, &pctx->cache_model); + if (val < pctx->num_syms) { + int idx, j; + + + idx = 0; + for (i = 0; i < pctx->cache_size; i++) { + for (j = 0; j < num_ngb; j++) + if (pctx->cache[i] == ngb[j]) + break; + if (j == num_ngb) { + if (idx == val) + break; + idx++; + } + } + val = FFMIN(i, pctx->cache_size - 1); + pix = pctx->cache[val]; + } else { + pix = arith_get_model_sym(acoder, &pctx->full_model); + for (i = 0; i < pctx->cache_size - 1; i++) + if (pctx->cache[i] == pix) + break; + val = i; + } + if (val) { + for (i = val; i > 0; i--) + pctx->cache[i] = pctx->cache[i - 1]; + pctx->cache[0] = pix; + } + + return pix; +} + +static int decode_pixel_in_context(ArithCoder *acoder, PixContext *pctx, + uint8_t *src, int stride, int x, int y, + int has_right) +{ + uint8_t neighbours[4]; + uint8_t ref_pix[4]; + int nlen; + int layer = 0, sub; + int pix; + int i, j; + + if (!y) { + memset(neighbours, src[-1], 4); + } else { + neighbours[TOP] = src[-stride]; + if (!x) { + neighbours[TOP_LEFT] = neighbours[LEFT] = neighbours[TOP]; + } else { + neighbours[TOP_LEFT] = src[-stride - 1]; + neighbours[ LEFT] = src[-1]; + } + if (has_right) + neighbours[TOP_RIGHT] = src[-stride + 1]; + else + neighbours[TOP_RIGHT] = neighbours[TOP]; + } + + sub = 0; + if (x >= 2 && src[-2] == neighbours[LEFT]) + sub = 1; + if (y >= 2 && src[-2 * stride] == neighbours[TOP]) + sub |= 2; + + nlen = 1; + ref_pix[0] = neighbours[0]; + for (i = 1; i < 4; i++) { + for (j = 0; j < nlen; j++) + if (ref_pix[j] == neighbours[i]) + break; + if (j == nlen) + ref_pix[nlen++] = neighbours[i]; + } + + switch (nlen) { + case 1: + case 4: + layer = 0; + break; + case 2: + if (neighbours[TOP] == neighbours[TOP_LEFT]) { + if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) + layer = 3; + else if (neighbours[LEFT] == neighbours[TOP_LEFT]) + layer = 2; + else + layer = 4; + } else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) { + if (neighbours[LEFT] == neighbours[TOP_LEFT]) + layer = 1; + else + layer = 5; + } else if (neighbours[LEFT] == neighbours[TOP_LEFT]) { + layer = 6; + } else { + layer = 0; + } + break; + case 3: + if (neighbours[TOP] == neighbours[TOP_LEFT]) + layer = 0; + else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) + layer = 1; + else if (neighbours[LEFT] == neighbours[TOP_LEFT]) + layer = 2; + else if (neighbours[TOP_RIGHT] == neighbours[TOP]) + layer = 3; + else if (neighbours[TOP] == neighbours[LEFT]) + layer = 4; + else + layer = 5; + break; + } + + pix = arith_get_model_sym(acoder, &pctx->sec_models[nlen - 1][layer][sub]); + if (pix < nlen) + return ref_pix[pix]; + else + return decode_pixel(acoder, pctx, ref_pix, nlen); +} + +static int decode_region(MSS1Context *ctx, ArithCoder *acoder, uint8_t *dst, + int x, int y, int width, int height, int stride, + PixContext *pctx) +{ + int i, j; + + dst += x + y * stride; + + dst[0] = decode_top_left_pixel(acoder, pctx); + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + if (!i && !j) + continue; + + dst[i] = decode_pixel_in_context(acoder, pctx, dst + i, stride, + i, j, width - i - 1); + } + dst += stride; + } + + return 0; +} + +static int decode_region_masked(MSS1Context *ctx, ArithCoder *acoder, + uint8_t *dst, int stride, uint8_t *mask, + int mask_stride, int x, int y, + int width, int height, + PixContext *pctx) +{ + int i, j; + + dst += x + y * stride; + mask += x + y * mask_stride; + + if (mask[0] != 0xFF) + dst[0] = decode_top_left_pixel(acoder, pctx); + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + if (!i && !j || mask[i] != 0xFF) + continue; + + dst[i] = decode_pixel_in_context(acoder, pctx, dst + i, stride, + i, j, width - i - 1); + } + dst += stride; + mask += mask_stride; + } + + return 0; +} + +static av_cold void codec_init(MSS1Context *ctx) +{ + model_init(&ctx->intra_region, 2, THRESH_ADAPTIVE); + model_init(&ctx->inter_region, 2, THRESH_ADAPTIVE); + model_init(&ctx->split_mode, 3, THRESH_HIGH); + model_init(&ctx->edge_mode, 2, THRESH_HIGH); + model_init(&ctx->pivot, 3, THRESH_LOW); + pixctx_init(&ctx->intra_pix_ctx, 8); + pixctx_init(&ctx->inter_pix_ctx, 2); + ctx->corrupted = 1; +} + +static void codec_reset(MSS1Context *ctx) +{ + model_reset(&ctx->intra_region); + model_reset(&ctx->inter_region); + model_reset(&ctx->split_mode); + model_reset(&ctx->edge_mode); + model_reset(&ctx->pivot); + pixctx_reset(&ctx->intra_pix_ctx); + pixctx_reset(&ctx->inter_pix_ctx); + + ctx->corrupted = 0; +} + +static int decode_pal(MSS1Context *ctx, ArithCoder *acoder) +{ + int i, ncol, r, g, b; + uint32_t *pal = ctx->pal + 256 - ctx->free_colours; + + if (!ctx->free_colours) + return 0; + + ncol = arith_get_number(acoder, ctx->free_colours + 1); + for (i = 0; i < ncol; i++) { + r = arith_get_bits(acoder, 8); + g = arith_get_bits(acoder, 8); + b = arith_get_bits(acoder, 8); + *pal++ = (r << 16) | (g << 8) | b; + } + + return 0; +} + +static int decode_pivot(MSS1Context *ctx, ArithCoder *acoder, int base) +{ + int val, inv; + + inv = arith_get_model_sym(acoder, &ctx->edge_mode); + val = arith_get_model_sym(acoder, &ctx->pivot) + 1; + + if (val > 2) { + if ((base + 1) / 2 - 2 <= 0) { + ctx->corrupted = 1; + return 0; + } + val = arith_get_number(acoder, (base + 1) / 2 - 2) + 3; + } + + if (val == base) { + ctx->corrupted = 1; + return 0; + } + + return inv ? base - val : val; +} + +static int decode_region_intra(MSS1Context *ctx, ArithCoder *acoder, + int x, int y, int width, int height) +{ + int mode; + + mode = arith_get_model_sym(acoder, &ctx->intra_region); + + if (!mode) { + int i, pix; + int stride = ctx->pic_stride; + uint8_t *dst = ctx->pic_start + x + y * stride; + + pix = decode_top_left_pixel(acoder, &ctx->intra_pix_ctx); + for (i = 0; i < height; i++, dst += stride) + memset(dst, pix, width); + } else { + return decode_region(ctx, acoder, ctx->pic_start, + x, y, width, height, ctx->pic_stride, + &ctx->intra_pix_ctx); + } + + return 0; +} + +static int decode_intra(MSS1Context *ctx, ArithCoder *acoder, + int x, int y, int width, int height) +{ + int mode, pivot; + + if (ctx->corrupted) + return -1; + + mode = arith_get_model_sym(acoder, &ctx->split_mode); + + switch (mode) { + case SPLIT_VERT: + pivot = decode_pivot(ctx, acoder, height); + if (ctx->corrupted) + return -1; + if (decode_intra(ctx, acoder, x, y, width, pivot)) + return -1; + if (decode_intra(ctx, acoder, x, y + pivot, width, height - pivot)) + return -1; + break; + case SPLIT_HOR: + pivot = decode_pivot(ctx, acoder, width); + if (ctx->corrupted) + return -1; + if (decode_intra(ctx, acoder, x, y, pivot, height)) + return -1; + if (decode_intra(ctx, acoder, x + pivot, y, width - pivot, height)) + return -1; + break; + case SPLIT_NONE: + return decode_region_intra(ctx, acoder, x, y, width, height); + default: + return -1; + } + + return 0; +} + +static int decode_region_inter(MSS1Context *ctx, ArithCoder *acoder, + int x, int y, int width, int height) +{ + int mode; + + mode = arith_get_model_sym(acoder, &ctx->inter_region); + + if (!mode) { + mode = decode_top_left_pixel(acoder, &ctx->inter_pix_ctx); + if (mode != 0xFF) { + return 0; + } else { + return decode_region_intra(ctx, acoder, x, y, width, height); + } + } else { + if (decode_region(ctx, acoder, ctx->mask, + x, y, width, height, ctx->mask_linesize, + &ctx->inter_pix_ctx) < 0) + return -1; + return decode_region_masked(ctx, acoder, ctx->pic_start, + -ctx->pic.linesize[0], ctx->mask, + ctx->mask_linesize, + x, y, width, height, + &ctx->intra_pix_ctx); + } + + return 0; +} + +static int decode_inter(MSS1Context *ctx, ArithCoder *acoder, + int x, int y, int width, int height) +{ + int mode, pivot; + + if (ctx->corrupted) + return -1; + + mode = arith_get_model_sym(acoder, &ctx->split_mode); + + switch (mode) { + case SPLIT_VERT: + pivot = decode_pivot(ctx, acoder, height); + if (decode_inter(ctx, acoder, x, y, width, pivot)) + return -1; + if (decode_inter(ctx, acoder, x, y + pivot, width, height - pivot)) + return -1; + break; + case SPLIT_HOR: + pivot = decode_pivot(ctx, acoder, width); + if (decode_inter(ctx, acoder, x, y, pivot, height)) + return -1; + if (decode_inter(ctx, acoder, x + pivot, y, width - pivot, height)) + return -1; + break; + case SPLIT_NONE: + return decode_region_inter(ctx, acoder, x, y, width, height); + default: + return -1; + } + + return 0; +} + +static int mss1_decode_frame(AVCodecContext *avctx, void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MSS1Context *c = avctx->priv_data; + GetBitContext gb; + ArithCoder acoder; + int pal_changed = 0; + int ret; + + init_get_bits(&gb, buf, buf_size * 8); + arith_init(&acoder, &gb); + + c->pic.reference = 3; + c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | + FF_BUFFER_HINTS_REUSABLE; + if ((ret = avctx->reget_buffer(avctx, &c->pic)) < 0) { + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); + return ret; + } + + c->pic_start = c->pic.data[0] + c->pic.linesize[0] * (avctx->height - 1); + c->pic_stride = -c->pic.linesize[0]; + if (!arith_get_bit(&acoder)) { + codec_reset(c); + pal_changed = decode_pal(c, &acoder); + c->corrupted = decode_intra(c, &acoder, 0, 0, + avctx->width, avctx->height); + c->pic.key_frame = 1; + c->pic.pict_type = AV_PICTURE_TYPE_I; + } else { + if (c->corrupted) + return AVERROR_INVALIDDATA; + c->corrupted = decode_inter(c, &acoder, 0, 0, + avctx->width, avctx->height); + c->pic.key_frame = 0; + c->pic.pict_type = AV_PICTURE_TYPE_P; + } + if (c->corrupted) + return AVERROR_INVALIDDATA; + memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE); + c->pic.palette_has_changed = pal_changed; + + *data_size = sizeof(AVFrame); + *(AVFrame*)data = c->pic; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int mss1_decode_init(AVCodecContext *avctx) +{ + MSS1Context * const c = avctx->priv_data; + int i; + + c->avctx = avctx; + + if (avctx->extradata_size < 52 + 256 * 3) { + av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d\n", + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + if (AV_RB32(avctx->extradata) < avctx->extradata_size) { + av_log(avctx, AV_LOG_ERROR, + "Insufficient extradata size: expected %d got %d\n", + AV_RB32(avctx->extradata), + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d\n", + AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8)); + c->free_colours = AV_RB32(avctx->extradata + 48); + av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours); + avctx->coded_width = AV_RB32(avctx->extradata + 20); + avctx->coded_height = AV_RB32(avctx->extradata + 24); + + av_log(avctx, AV_LOG_DEBUG, "Display dimensions %dx%d\n", + AV_RB32(avctx->extradata + 12), AV_RB32(avctx->extradata + 16)); + av_log(avctx, AV_LOG_DEBUG, "Coded dimensions %dx%d\n", + avctx->coded_width, avctx->coded_height); + av_log(avctx, AV_LOG_DEBUG, "%g frames per second\n", + av_int2float(AV_RB32(avctx->extradata + 28))); + av_log(avctx, AV_LOG_DEBUG, "Bitrate %d bps\n", + AV_RB32(avctx->extradata + 32)); + av_log(avctx, AV_LOG_DEBUG, "Max. lead time %g ms\n", + av_int2float(AV_RB32(avctx->extradata + 36))); + av_log(avctx, AV_LOG_DEBUG, "Max. lag time %g ms\n", + av_int2float(AV_RB32(avctx->extradata + 40))); + av_log(avctx, AV_LOG_DEBUG, "Max. seek time %g ms\n", + av_int2float(AV_RB32(avctx->extradata + 44))); + + for (i = 0; i < 256; i++) + c->pal[i] = AV_RB24(avctx->extradata + 52 + i * 3); + + avctx->pix_fmt = PIX_FMT_PAL8; + + c->mask_linesize = FFALIGN(avctx->width, 16); + c->mask = av_malloc(c->mask_linesize * avctx->height); + if (!c->mask) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate mask plane\n"); + return AVERROR(ENOMEM); + } + + avctx->coded_frame = &c->pic; + + codec_init(c); + + return 0; +} + +static av_cold int mss1_decode_end(AVCodecContext *avctx) +{ + MSS1Context * const c = avctx->priv_data; + + if (c->pic.data[0]) + avctx->release_buffer(avctx, &c->pic); + av_freep(&c->mask); + + return 0; +} + +AVCodec ff_mss1_decoder = { + .name = "mss1", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_MSS1, + .priv_data_size = sizeof(MSS1Context), + .init = mss1_decode_init, + .close = mss1_decode_end, + .decode = mss1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MS Screen 1"), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 46b0f2358d..e049bee06a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,7 +27,7 @@ */ #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 15 +#define LIBAVCODEC_VERSION_MINOR 16 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index 922a863a84..efab7048ba 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -284,6 +284,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { CODEC_ID_VBLE, MKTAG('V', 'B', 'L', 'E') }, { CODEC_ID_DXTORY, MKTAG('x', 't', 'o', 'r') }, { CODEC_ID_ZEROCODEC, MKTAG('Z', 'E', 'C', 'O') }, + { CODEC_ID_MSS1, MKTAG('M', 'S', 'S', '1') }, { CODEC_ID_NONE, 0 } };