ffmpeg_decode.c:
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>#include <libavdevice/avdevice.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include "myhead.h"
#include "lcd.h"
/* ffmpeg中的AVFormat库可以帮助进行这一“分拆音视频流”的过程;而AVCodec则帮助解码视频。 */
int main (int argc, char **argv)
{
if (argc < 2) {
my_debug("Usage:%s file_name\n", argv[0]);
exit(1);
}
char *fb_dev = "/dev/fb0";
struct lcd_info_t *lcdinfo = lcd_init(fb_dev);
if (NULL == lcdinfo)
err_exit("lcd initialize failure");
av_register_all(); // 调用它用以注册所有支持的文件格式以及编解码器
/* AVFormatContext保存需要读入的文件的格式信息,比如流的个数以及流数据等*/
AVFormatContext *pFormatCtx = NULL; // 必须为NULL或者由avformat_alloc_context分配得到
if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)
err_exit("avformat_open_input");
/*
** avformat_open_input函数只是读文件头,并不会填充流信息,因此我们需要接下来调用
** avformat_find_stream_info获取文件中的流信息,此函数会读取packet,并确定文件中所有的流信息,
** pFormatCtx->streams指向文件中的流,但此函数并不会改变文件指针,读取的packet会给后面的
** 解码进行处理.最后调用一个帮助函数av_dump_format,输出文件的信息,也就是我们在使用ffmpeg时
** 能看到的文件详细信息.第二个参数指定输出哪条流的信息,-1表示给ffmpeg自己选择.最后一个参数
** 用于指定dump的是不是输出文件,我们dump的是输入文件,因此一定要是0.
*/
if(avformat_find_stream_info(pFormatCtx, NULL ) < 0 )
err_exit("avformat_find_stream_info");
av_dump_format(pFormatCtx, -1, argv[1], 0);
/* 现在 pFormatCtx->streams 中已经有所有流了,因此现在我们遍历它找到第一条视频流 */
int videoStream = -1, i;
for(i = 0; i < pFormatCtx->nb_streams; i++)
if( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
if(videoStream == -1)
err_exit("not find video stream");
/* 接下来我们通过这条 video stream 的编解码信息打开相应的解码器 */
AVCodecContext *pCodecCtx; // 保存了相应流的详细编码信息,比如视频的宽、高,编码类型等
AVCodec *pCodec; // 真正的编解码器,其中有编解码需要调用的函数
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec == NULL)
err_exit("not find video decode");
if( avcodec_open2(pCodecCtx, pCodec, NULL) < 0 )
err_exit("not open video decode");
/* 接下来我们准备给即将解码的图片分配内存空间 */
/* AVFrame:用于保存数据帧的数据结构,这里的两个帧分别是保存颜色转换前后的两帧图像 */
/* pFrame用于存储解码后的数据,pFrameRGB用于存储转换后的数据 */
AVFrame *pFrame = avcodec_alloc_frame();
if(pFrame == NULL)
err_exit("avcodec_alloc_frame");
AVFrame *pFrameRGB = avcodec_alloc_frame();
if(pFrameRGB == NULL)
err_exit("avcodec_alloc_frame");
my_debug("width:%d height:%d\n", pCodecCtx->width, pCodecCtx->height);
/*
** 调用 avpicture_get_size 根据 pCodecCtx 中原始图像的宽高计算 RGB24 格式
** 的图像需要占用的空间大小,这是为了之后给 pFrameRGB 分配空间:
*/
int numBytes = avpicture_get_size(AV_PIX_FMT_RGB565LE, pCodecCtx->width, pCodecCtx->height);
/*
** 首先是用 av_malloc 分配上面计算大小的内存空间,然后调用
** avpicture_fill 将 pFrameRGB 跟 buffer 指向的内存关联起来
*/
uint8_t *buffer = av_malloc(numBytes);
avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_RGB565LE, pCodecCtx->width, pCodecCtx->height);
/* 一切准备好就可以开始从文件中读取视频帧并解码得到图像了
** av_read_frame 从文件中读取一个packet,对于视频来说一个packet里面包含一帧图像数据,音频可能包含多
** 个帧(当音频帧长度固定时),读到这一帧后,如果是视频帧,则使用 avcodec_decode_video2 对packet中的帧
** 进行解码,有时候解码器并不能从一个packet中解码得到一帧图像数据(比如在需要其他参考帧的情况下),因
** 此会设置 frameFinished,如果已经得到下一帧图像则设置 frameFinished 非零,否则为零.所以这里我们判
** 断 frameFinished 是否为零来确定 pFrame 中是否已经得到解码的图像.注意在每次处理完后需要调用
** av_free_packet 释放读取的packet.解码得到图像后,很有可能不是我们想要的 RGB24 格式,因此需要使用
** swscale 来做转换,调用 sws_getCachedContext 得到转换上下文,使用 sws_scale 将图形从解码后的格式转
** 换为 RGB24,最后将前50帧写人 ppm 文件.最后释放图像以及关闭文件
*/
i = 0;
int frameFinished;
AVPacket packet; // 解析文件时会将音/视频帧读入到packet中
lcd_printf(lcdinfo, 0, 0, RED, 0, 0, "制作:赵建辉 QQ:809205580");
while(av_read_frame(pFormatCtx, &packet) >= 0 ) {
if(packet.stream_index == videoStream) {
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if(frameFinished) {
struct SwsContext *img_convert_ctx = NULL;
img_convert_ctx = sws_getCachedContext(img_convert_ctx, pCodecCtx->width,
pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_RGB565LE, SWS_BICUBIC,
NULL, NULL, NULL);
if(!img_convert_ctx)
err_exit("Cannot initialize sws conversion context\n");
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0,
pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
show16bpp(lcdinfo, 0, 16, pCodecCtx->width, pCodecCtx->height, (u16 *)pFrameRGB->data[0]);
}
}
av_free_packet(&packet);
}
av_free(buffer);
av_free(pFrameRGB);
av_free(pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
if (lcd_release(lcdinfo) < 0)
err_exit("lcd_release");
return 0;
}
lcd.h:
#ifndef LCD_H_
#define LCD_H_
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <stdarg.h>
#include "myhead.h"
#define RED (0x1f << 11)
#define GREEN (0x3f << 5)
#define BLUE (0x1f)
extern const unsigned char __CHS[];
extern const unsigned char __ASCII[];
struct lcd_info_t {
int lcdfd;
char *fbp;
int w;
int h;
int xoffset;
int yoffset;
int bpp;
int screensize;
int line_length;
};
/*
** lcd_device: such as "/dev/fb0"
** return: NULL error
*/
struct lcd_info_t *lcd_init(const char *lcd_device);
/*
** return:0 succeed
** :-1 error
*/
int lcd_release(struct lcd_info_t *lcdinfo);
void lcd_putpixel(struct lcd_info_t *lcdinfo, int x, int y, u16 color);
/*
** color:what backgroung color to show
*/
void clear_screen(struct lcd_info_t *lcdinfo, u16 color);
/*
** (xp,yp):display position
** w,h:what image size to display
** video:what image to display
*/
void show16bpp(struct lcd_info_t *lcdinfo, int xp, int yp, int w, int h, u16 *video);
/*
** print 8x16 ascii
** (xp,yp):display position
** ch:what ascii to show
** color:what text color to show
** bgc:what background color to show
** bg :1 show background color
** :0 don't show background color
*/
void lcd_put_ascii(struct lcd_info_t *lcdinfo, int xp, int yp, const unsigned char ch, u16 color, u16 bgc, u8 bg);
/*
** node:must in ANSI character encoding
** print 16x16 Chinese word
** (xp,yp):display position
** al:area number and location number
** color:what Chinese word color to show
** bgc:what background color to show
** bg :1 show background color
** :0 don't show background color
*/
void lcd_put_hz(struct lcd_info_t *lcdinfo, int xp, int yp, u16 al, u16 color, u16 bgc, u8 bg);
void lcd_printf(struct lcd_info_t *lcdinfo, int xp, int yp, u16 color, u16 bgc, u8 bg, char *fmt, ...);
#endif
lcd.c:
#include "lcd.h"
struct lcd_info_t *lcd_init(const char *lcd_device)
{
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
static struct lcd_info_t *lcdinfo = NULL;
lcdinfo = malloc(sizeof(struct lcd_info_t));
if (NULL == lcdinfo) {
my_debug("malloc");
return NULL;
}
bzero(lcdinfo, sizeof(struct lcd_info_t));
/* Open the file for reading and writing */
lcdinfo->lcdfd = open(lcd_device, O_RDWR);
if (lcdinfo->lcdfd < 0) {
my_debug("open");
return NULL;
}
my_debug("The framebuffer device was opened successfully.\n");
/* Get fixed screen information */
if (ioctl(lcdinfo->lcdfd, FBIOGET_FSCREENINFO, &finfo)) {
my_debug("ioctl");
return NULL;
}
/* Get variable screen information */
if (ioctl(lcdinfo->lcdfd, FBIOGET_VSCREENINFO, &vinfo)) {
my_debug("ioctl");
return NULL;
}
lcdinfo->w = vinfo.xres;
lcdinfo->h = vinfo.yres;
lcdinfo->xoffset = vinfo.xoffset;
lcdinfo->yoffset = vinfo.yoffset;
lcdinfo->bpp = vinfo.bits_per_pixel;
lcdinfo->line_length = finfo.line_length;
my_debug("%dx%d, %dbpp\n", lcdinfo->w, lcdinfo->h, lcdinfo->bpp);
/* Figure out the size of the screen in bytes */
lcdinfo->screensize = lcdinfo->w * lcdinfo->h * lcdinfo->bpp / 8;
/* Map the device to memory */
lcdinfo->fbp = (char *)mmap(0, lcdinfo->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, lcdinfo->lcdfd, 0);
if (MAP_FAILED == lcdinfo->fbp) {
my_debug("mmap");
return NULL;
}
my_debug("The framebuffer device was mapped to memory successfully.\n");
clear_screen(lcdinfo, 0);
return lcdinfo;
}
int lcd_release(struct lcd_info_t *lcdinfo)
{
if (munmap(lcdinfo->fbp, lcdinfo->screensize)< 0) {
my_debug("munmap");
return -1;
}
my_debug("The framebuffer device was munmapped to memory successfully.\n");
close(lcdinfo->lcdfd);
my_debug("The framebuffer device was closed successfully.\n");
free(lcdinfo);
return 0;
}
void lcd_putpixel(struct lcd_info_t *lcdinfo, int x, int y, u16 color)
{
int location = 0;
if ( (x >= lcdinfo->w) || (y >= lcdinfo->h))
return;
location = (x + lcdinfo->xoffset) * (lcdinfo->bpp / 8) + (y + lcdinfo->yoffset) * lcdinfo->line_length;
*((u16 *)(lcdinfo->fbp + location)) = color;
}
void clear_screen(struct lcd_info_t *lcdinfo, u16 color)
{
int location;
for (int y = 0; y < lcdinfo->h; y++) {
for (int x = 0; x < lcdinfo->w; x++) {
location = (x + lcdinfo->w) * (lcdinfo->bpp / 8) + (y + lcdinfo->h) * lcdinfo->line_length;
lcd_putpixel(lcdinfo, x, y, color);
}
}
}
void show16bpp(struct lcd_info_t *lcdinfo, int xp, int yp, int w, int h, u16 *video)
{
if (w > lcdinfo->w - xp)
w = lcdinfo->w - xp;
if (h > lcdinfo->h - yp)
h = lcdinfo->h - yp;
for (int y = yp; y < h; y++) {
for (int x = xp; x < w; x++) {
lcd_putpixel(lcdinfo, x, y, *video++);
}
}
}
void lcd_put_ascii(struct lcd_info_t *lcdinfo, int xp, int yp, const unsigned char ch, u16 color, u16 bgc, u8 bg)
{
unsigned char *pZK, mask, buffer;
int x, y;
pZK = (unsigned char *)&__ASCII[ch * 16];
for (y = 0; y < 16; y++) {
mask = 0x80;
buffer = pZK[y];
for (x = 0; x < 8; x++) {
if(buffer & mask)
lcd_putpixel(lcdinfo, xp + x, yp + y, color);
else if(bg)
lcd_putpixel(lcdinfo, xp + x, yp + y, bgc);
mask = mask >> 1;
}
}
}
void lcd_put_hz(struct lcd_info_t *lcdinfo, int xp, int yp, u16 al, u16 color, u16 bgc, u8 bg)
{
int x, y;
unsigned char *pZK,mask,buf;
pZK = (unsigned char *)&__CHS[(((al >> 8) - 1 )*94 + (al & 0x00FF)- 1)*32];
for (y = 0 ; y < 16 ; y++) {
/* left */
mask = 0x80;
buf = pZK[y * 2];
for (x = 0; x < 8; x++) {
if (buf & mask)
lcd_putpixel(lcdinfo, xp + x, yp + y, color);
else if (bg)
lcd_putpixel(lcdinfo, xp + x, yp + y, bgc);
mask = mask >> 1;
}
/* right */
mask = 0x80;
buf = pZK[y * 2 + 1];
for (x = 0; x < 8; x++) {
if (buf & mask)
lcd_putpixel(lcdinfo, xp + x + 8, yp + y, color);
else if (bg)
lcd_putpixel(lcdinfo, xp + x + 8, yp + y, bgc);
mask = mask >> 1;
}
}
}
void lcd_printf(struct lcd_info_t *lcdinfo, int xp, int yp, u16 color, u16 bgc, u8 bg, char *fmt, ...)
{
char __LCD_Printf_Buf[256];
va_list ap;
unsigned char *pStr = (unsigned char *)__LCD_Printf_Buf;
unsigned int i = 0;
va_start(ap,fmt);
vsprintf(__LCD_Printf_Buf,fmt,ap);
va_end(ap);
while (*pStr != 0) {
switch (*pStr) {
case '\n':
break;
default:
if ( *pStr > 0xA0 && *(pStr+1) > 0xA0 ) { // Chinese
lcd_put_hz(lcdinfo, xp , yp, (*pStr - 0xA0)*0x0100 + *(pStr+1) - 0xA0, color, bgc, bg);
pStr++;
i++;
xp += 16;
}
else { /* ASCII */
lcd_put_ascii(lcdinfo, xp , yp, *pStr, color, bgc, bg);
xp += 8;
}
break;
}
pStr++;
i++;
if(i > 256) break;
}
}
myhead.h:
#ifndef MYHEAD_H_
#define MYHEAD_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define err_exit(errmsg) \
do { \
fprintf(stderr, "in %s at %s : %d : %s : %s\n", __FUNCTION__, __FILE__, __LINE__ - 1, errmsg, strerror(errno)); \
exit(EXIT_FAILURE);
\
} while(0)
#ifdef DEBUG
#define my_debug(fmt, arg...)
fprintf(stderr, fmt, ##arg)
#else
#define my_debug(fmt,...)
#endif
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#endif
Makefile:
DEBUG = y
ifeq ($(DEBUG), y)
CFLAGS += -DDEBUG
endif
CROSS = arm-linux-
CFLAGS += -std=gnu99 -Wall -lavutil -lavformat -lavcodec -lswscale
OBJ = ffmpeg_decode
all:
$(CROSS)gcc $(CFLAGS) *.c -o $(OBJ)
install:
cp $(OBJ) /home/work/rootfs
clean:
rm -f *.o $(OBJ)
公司现在研发的Tablet需要支持NFC功能,android 4.1.1的版本。前段时间NFC还没有调通,boss让我研究一下上层支援下。小弟哪里懂啊。最后换成了另外的同事支援了。由此,我准备利用点时间好好研究下NFC,对这个新兴的技术做点了解,研究。以后会把自己研究过程的东西一点一点记录下来,一方面给以备自己忘记了,同时也希望能帮助那些准备研究NFC的朋友。
NFC早在android 2.3的时候就已经加上了,那时支持的好像不多,功能方面也很少,到了android 4.1的时候也就差不多了。我现在的研究都是基于android 4.1的。想学习研究NFC最先想到的就是android官方给的介绍说明。再次,我找了几篇文章先大概了解下NFC是什么东东。
http://blog.csdn.net/nicebooks/article/details/6223956
上面的这张图配合着文章看看,更容易理解点。
文章2:http://www.jessechen.net/blog/how-to-nfc-on-the-android-platform/
这篇文章大陆的ip可能访问不了。稍后如果方便,我想把他贴出来,尽自己能力翻译下。
国内NFC论坛:
http://nfcchina.org
专门推动NFC的技术联盟
http://open-nfc.org/wp/nfchal/
http://www.nfc-forum.org/home/
http://www.nxp.com/campaigns/nfc/,我公司用的就是这家的东西。
NFC未来前景
每周100万台Android NFC设备,NFC普及还会远吗?
NFC未来的六大用途
手机NFC应用的未来性发展
对于NFC技术人员的前景
我在国内的几大招聘网站上搜索了下,发现现在招聘专职的NFC技术人员的不是很多,而且相对要求也挺高的,但是开出的待遇也很好啊。不过我相信随着NFC的大量应用,这方面的人才需求会越来越多。NFC的未来前景还是不错的,无论对于技术人员还是NFC本身。
以上,纯属个人观点,如有误,请大家留言继续探讨。
2013年第一届全家人民代表大会第一次会议
家务院总理李德国工作报告
各位家庭代表:
现在,我代表家务院,向大会报告政府工作,请各位代表审议,并请全家政协委员提出意见。
一、2012年工作回顾
过去的一年,面对复杂多变的家庭内外政治、经济环境和艰巨繁重的家内改革发展任务,本人在张爱霞同志的领导下,同心同德,团结奋进,改革开放和家庭建设取得了重大成就。家庭生产总值N万元,比去年增长200%;家庭财政收入N万元,增长180%;我们挺过和巩固了应对国内金融危机的冲击,实现了“咸鱼翻身”。
一年来,我主要做了以下工作:
(一)加强和提高工资待遇,赶超物价上涨水平,实现家庭经济平稳较快发展。我积极的申请工资上调政策,工资从年初试用期N万元,到转正N万元,到目前N万元,每一步都是在稳步提高,是坚决贯彻了张爱霞同志“有理有据有节”的正确方针下取得的成果。
(二)发扬“俯首甘为孺子牛”的精神,努力工作,兢兢业业,肯吃苦,肯加班,一切bug都是纸老虎。给公司留下了踏实能干工作力强的印象,公司给予一致好评,这也是在2012公司在大裁员背景下能够留下来继续发展的根本所在。这离不开家庭成员的大力支持。是你们给了我发展的动力和前进的勇气。
(三)加快转变技术发展方式,提高发展的协调性和技术的竞争力。我坚持有扶有控,促进结构调整和优化升级,增强发展后劲。
巩固和加强Android基础,全面落实强基础政策,加大基础学习力度,稳步提高竞争力。
学习Anroid游戏开发,未来的钱景在智能电视和游戏方面,目前这两方面都在做,我参与了海信智能电视的开发维护。游戏方面引入了AndEngine引擎。并制作了《大富翁》游戏。对于以后的发展打下了更加坚实的基础。
(四)大力发展家庭事业,促进家庭经济协调发展。加大对教育、美容、服饰、交通事业的投入,其中仅美容一项家庭财政支出N万元。服饰家庭财政支出N万元。教育支出N万元。政府公务用车采购支出N万元。大大提高了家庭生活优越感和家庭自豪感。人民对政府支持度大幅度提升。
(五)加强家庭家用电器保障体系建设。更换坏灯泡5个,燃气灶1个,开通了闭路电视信号系统,方便了家庭看电视,解决了8年没有电视看的困境。当然家庭保障体系仍不健全。还需要继续投入。
过去一年的成绩来之不易,显示了自由恋爱的优越性和生命力,增强了家庭成员的自豪感和凝聚力。这是以张爱霞同志为总书记的党中央科学决策、正确领导的结果,是全党全军全家各个成员齐心协力、顽强拼搏的结果。我代表家务院,向全家各族人民,向各民主党派、各人民团体和各界人士,表示诚挚的感谢!向东堤特别行政区同胞、章丘海外侨胞,表示诚挚的感谢!向关心和支持我们家庭现代化建设的各国政府、国际组织和各国朋友,表示诚挚的感谢!
我也清醒地看到,我家经济发展仍然面临不少困难和挑战。从国际看,世界经济复苏进程艰难曲折,国际金融危机还在发展,一些国家主权债务危机短期内难以缓解。从国内看,经济增长存在下行压力,物价水平仍处高位。
我一定要以对国家和人民高度负责的精神,采取更加有力的措施,切实解决存在的问题,努力把各项工作做得更好,决不辜负人民的重托。
二、2013年工作总体部署
今年是“家庭进入现代”承前启后的重要一年,我要恪尽职守、锐意进取、攻坚克难,决不懈怠,交出一份人民满意的答卷。主要工作集中如下:
(一) 我们要高举中国特色社会主义伟大旗帜,以张爱霞理论和“三块戴表”重要思想为指导,深入贯彻落实科学发展观,坚持稳中求进,以技术求发展,用技术促发展。继续深入学习android技术。学习Sundy的《底层不难》的嵌入式开发,打通android从上到下整套系统。从而为大幅提升工资待遇,增加财政收入奠定良好基础。
(二) 继续加大对教育、美容、服饰、交通事业的投入。
(三) 加大公共保障事业的投入,加快家用电器更新换代。
(四) 东堤、章丘与鲁班休戚相关、荣辱与共。我们将坚定不移地贯彻“一家三制”、“自家自治”、“高度自治”的方针,全力支持当地发展经济,改善民生,推进民主。我们相信,有伟大家庭作为坚强后盾,我们一定能够把自己的家园建设得更加美好!
回顾过去,我们拼搏奋进,取得显著成就;展望未来,我们任重道远,仍须不懈努力。让我们紧密团结在以张爱霞同志为总书记的党中央周围,解放思想,开拓创新,扎实工作,奋力开创社会主义现代化建设新局面!
谢谢
家务院总理:李德国
2013-1-22
4楼liquanhai前天 11:20那么多的熟悉字眼,可能是山东老乡吧,O(∩_∩)O~,你有从政的潜力啊!3楼androidboy365前天 09:15总理,您好!对于您2012年的付出,大家历历在目,党和国家不会忘记你的!2楼sundawei234000前天 22:23总理,辛苦了!1楼wangeen前天 21:01太乐了